[jboss-svn-commits] JBL Code SVN: r19665 - in labs/jbossrules/branches/temporal_rete/drools-core-window-ITA: src and 100 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Mon Apr 21 06:35:42 EDT 2008


Author: mgroch
Date: 2008-04-21 06:35:38 -0400 (Mon, 21 Apr 2008)
New Revision: 19665

Added:
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/.classpath
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/.project
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/build.properties
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/pom.xml
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/repository/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/codehaus/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/Agenda.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/CheckedDroolsException.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ClockType.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/EntryPointInterface.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/FactException.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/FactHandle.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/InitialFact.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/IntegrationException.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ObjectFilter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/Otherwise.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/PackageIntegrationException.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ProcessIntegrationException.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/QueryResult.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/QueryResults.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuleBase.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuleBaseConfiguration.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuleBaseEventManager.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuleBaseFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuleIntegrationException.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuntimeDroolsException.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/StatefulSession.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/StatelessSession.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/StatelessSessionResult.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/TemporalSession.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/Visitor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/WorkingMemory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/WorkingMemoryEventManager.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/AgentEventListener.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/DirectoryScanner.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/FileLoader.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/FileScanner.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/HttpClientImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/IHttpClient.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/PackageProvider.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/RuleAgent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/RuleBaseAgentCache.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/URLScanner.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/AnnotationVisitor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/AnnotationWriter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Attribute.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/ByteVector.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/ClassAdapter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/ClassReader.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/ClassVisitor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/ClassWriter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Edge.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/FieldVisitor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/FieldWriter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Handler.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Item.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Label.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/MethodAdapter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/MethodVisitor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/MethodWriter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Opcodes.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Type.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/attrs/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/attrs/StackMapAttribute.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/attrs/StackMapFrame.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/attrs/StackMapTableAttribute.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/attrs/StackMapType.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/attrs/package.html
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/AdviceAdapter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/EmptyVisitor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/GeneratorAdapter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/LocalVariablesSorter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/Method.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/SerialVersionUIDAdder.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/StaticInitMerger.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/TableSwitchGenerator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/package.html
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/package.html
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/signature/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/signature/SignatureReader.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/signature/SignatureVisitor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/signature/SignatureWriter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/signature/package.html
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/ASMifierAbstractVisitor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/ASMifierAnnotationVisitor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/ASMifierClassVisitor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/ASMifierFieldVisitor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/ASMifierMethodVisitor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/AbstractVisitor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/CheckAnnotationAdapter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/CheckFieldAdapter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/CheckMethodAdapter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceAbstractVisitor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceAnnotationVisitor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceClassVisitor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceFieldVisitor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceMethodVisitor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceSignatureVisitor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/attrs/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/attrs/ASMStackMapAttribute.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/attrs/ASMStackMapTableAttribute.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/attrs/ASMifiable.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/attrs/Traceable.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/attrs/package.html
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/package.html
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/WorkingMemoryConsoleLogger.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/WorkingMemoryFileLogger.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/WorkingMemoryInMemoryLogger.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/WorkingMemoryLogger.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/ActivationLogEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/ActivationLogEventFilter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/ILogEventFilter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/LogEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/ObjectLogEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/RuleBaseLogEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/RuleFlowGroupLogEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/RuleFlowLogEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/RuleFlowNodeLogEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/WorkingMemoryLogEventFilter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/AsyncFireAllRulesRuleBaseUpdateListener.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/BaseClassFieldExtractor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/BaseDuration.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/BaseEvaluator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassFieldExtractor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassFieldExtractorCache.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassFieldExtractorFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassObjectFilter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassObjectType.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassTypeResolver.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/CopyIdentifiersGlobalExporter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/DefaultConsequenceExceptionHandler.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/DefaultKnowledgeHelper.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/DelegateJavaFactHandler.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/DroolsQuery.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/FieldFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/FireAllRulesRuleBaseUpdateListener.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/JavaFactRegistryEntry.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/MapGlobalResolver.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ModifyInterceptor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ReferenceOriginalGlobalExporter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/RuleNameEndsWithAgendaFilter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/RuleNameEqualsAgendaFilter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/RuleNameMatchesAgendaFilter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/RuleNameStartsWithAgendaFilter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/SalienceInteger.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/SequentialKnowledgeHelper.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ShadowProxy.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ShadowProxyFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ShadowProxyHelper.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/SimpleValueType.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/TypeResolver.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ValueType.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/AccumulateFunction.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/AverageAccumulateFunction.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/CountAccumulateFunction.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/JavaAccumulatorFunctionExecutor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/MVELAccumulatorFunctionExecutor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/MaxAccumulateFunction.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/MinAccumulateFunction.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/SumAccumulateFunction.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/dataproviders/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/dataproviders/MVELDataProvider.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/AfterEvaluatorDefinition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/BeforeEvaluatorDefinition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/CoincidesEvaluatorDefinition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/ComparableEvaluatorsDefinition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/DuringEvaluatorDefinition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/EqualityEvaluatorsDefinition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/EvaluatorCache.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/EvaluatorDefinition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/EvaluatorRegistry.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/FinishedByEvaluatorDefinition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/FinishesEvaluatorDefinition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/IncludesEvaluatorDefinition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/MatchesEvaluatorsDefinition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/MeetsEvaluatorDefinition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/MetByEvaluatorDefinition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/Operator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/OverlappedByEvaluatorDefinition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/OverlapsEvaluatorDefinition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/SetEvaluatorsDefinition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/SoundslikeEvaluatorsDefinition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/StartedByEvaluatorDefinition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/StartsEvaluatorDefinition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/ArrayExtractor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseBooleanClassFieldExtractor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseByteClassFieldExtractor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseCharClassFieldExtractor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseDoubleClassFieldExtractor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseFloatClassFieldExtractor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseIntClassFieldExtractor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseLongClassFieldExtractors.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseObjectClassFieldExtractor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseShortClassFieldExtractor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/MVELClassFieldExtractor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/SelfReferenceClassFieldExtractor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/field/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/field/BooleanFieldImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/field/DoubleFieldImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/field/LongFieldImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/field/ObjectFieldImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/DroolsMVELFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/DroolsMVELGlobalVariable.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/DroolsMVELKnowledgeHelper.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/DroolsMVELLocalDeclarationVariable.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/DroolsMVELPreviousDeclarationVariable.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/LocalVariableResolver.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELAccumulator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELAction.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELCalendarCoercion.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELConsequence.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELDateCoercion.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELDebugHandler.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELEvalExpression.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELPredicateExpression.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELReturnValueEvaluator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELReturnValueExpression.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELSalienceExpression.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/AbstractFactHandleFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/AbstractRuleBase.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/AbstractWorkingMemory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ActivationGroupImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ActivationGroupNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/AgendaGroupFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/AgendaItem.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ArrayAgendaGroup.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ArrayAgendaGroupFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/BaseNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/BetaConstraints.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/BinaryHeapQueueAgendaGroup.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ConcurrentNodeMemories.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/DefaultAgenda.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/DefaultBetaConstraints.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/DefaultFactHandle.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/DoubleBetaConstraints.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/DroolsObjectInputStream.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EmptyBetaConstraints.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EqualityAssertMapComparator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EqualityKey.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EqualityKeyComparator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EventFactHandle.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EventSupport.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/IdentityAssertMapComparator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InstanceEqualsConstraint.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InstanceNotEqualsConstraint.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalAgenda.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalAgendaGroup.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalFactHandle.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalRuleBase.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalRuleFlowGroup.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalWorkingMemory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalWorkingMemoryActions.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/LogicalDependency.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/NetworkNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/NodeMemories.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/NodeMemory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ObjectStore.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/PriorityQueueAgendaGroupFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/PropagationContextImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/QuadroupleBetaConstraints.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/RuleFlowGroupImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/RuleFlowGroupListener.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/RuleFlowGroupNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ScheduledAgendaItem.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/Scheduler.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/SequentialAgendaGroupImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/SingleBetaConstraints.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/SingleThreadedObjectStore.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/TripleBetaConstraints.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/TruthMaintenanceSystem.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/TupleStartEqualsConstraint.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/WorkingMemoryAction.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/AssertObject.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/AssertObjects.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/Command.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/CommandExecutor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/DefaultExecutorService.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/ExecutorService.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/FireAllRules.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/Future.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/InternalFuture.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/RetractObject.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/UpdateObject.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/AbstractConflictResolver.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/ComplexityConflictResolver.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/CompositeConflictResolver.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/DepthConflictResolver.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/FifoConflictResolver.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/LifoConflictResolver.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/LoadOrderConflictResolver.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/RandomConflictResolver.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/RecencyConflictResolver.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/SalienceConflictResolver.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/SimplicityConflictResolver.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/TotalRecencyConflictResolver.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ActivationCancelledEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ActivationCreatedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ActivationEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterActivationFiredEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterFunctionRemovedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterPackageAddedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterPackageRemovedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterRuleAddedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterRuleBaseLockedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterRuleBaseUnlockedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterRuleRemovedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AgendaEventListener.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AgendaEventSupport.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AgendaGroupEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AgendaGroupPoppedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AgendaGroupPushedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeActivationFiredEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeFunctionRemovedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforePackageAddedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforePackageRemovedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeRuleAddedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeRuleBaseLockedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeRuleBaseUnlockedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeRuleRemovedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DebugAgendaEventListener.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DebugRuleFlowEventListener.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DebugWorkingMemoryEventListener.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DefaultAgendaEventListener.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DefaultRuleBaseEventListener.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DefaultRuleFlowEventListener.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DefaultWorkingMemoryEventListener.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ObjectInsertedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ObjectRetractedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ObjectUpdatedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleBaseEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleBaseEventListener.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleBaseEventSupport.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowCompletedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowEventListener.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowEventSupport.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowGroupActivatedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowGroupDeactivatedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowGroupEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowNodeTriggeredEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowStartedEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/WorkingMemoryEvent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/WorkingMemoryEventListener.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/WorkingMemoryEventSupport.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/Fact.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FactImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FactTemplate.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FactTemplateFieldExtractor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FactTemplateImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FactTemplateObjectType.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FieldTemplate.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FieldTemplateImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/Objenesis.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/ObjenesisBase.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/ObjenesisException.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/ObjenesisHelper.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/ObjenesisSerializer.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/ObjenesisStd.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/NullInstantiator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/ObjectInstantiator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/SerializationInstantiatorHelper.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/basic/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/basic/AccessibleInstantiator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/basic/ConstructorInstantiator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/basic/NewInstanceInstantiator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/basic/ObjectInputStreamInstantiator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/basic/ObjectStreamClassInstantiator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/gcj/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/gcj/GCJInstantiator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/gcj/GCJInstantiatorBase.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/gcj/GCJSerializationInstantiator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/jrockit/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/jrockit/JRockit131Instantiator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/jrockit/JRockitLegacyInstantiator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/sun/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/sun/Sun13Instantiator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/sun/Sun13InstantiatorBase.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/sun/Sun13SerializationInstantiator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/sun/SunReflectionFactoryInstantiator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/sun/SunReflectionFactorySerializationInstantiator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/strategy/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/strategy/BaseInstantiatorStrategy.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/strategy/InstantiatorStrategy.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/strategy/SerializingInstantiatorStrategy.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/strategy/StdInstantiatorStrategy.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/ParameterDefinition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/Process.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/Variable.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/VariableScope.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/Work.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/WorkDefinition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/WorkDefinitionExtension.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/DataType.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/DataTypeFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/InstanceDataTypeFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/NewInstanceDataTypeFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/BooleanDataType.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/FloatDataType.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/IntegerDataType.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/ListDataType.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/StringDataType.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/UndefinedDataType.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/ParameterDefinitionImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/ProcessImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/VariableImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/VariableScopeImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/WorkDefinitionExtensionImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/WorkDefinitionImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/WorkImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/validation/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/validation/ProcessValidationError.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/validation/ProcessValidator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/validation/impl/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/validation/impl/ProcessValidationErrorImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/ProcessInstance.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/ProcessInstanceFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/VariableScopeInstance.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/WorkItem.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/WorkItemHandler.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/WorkItemListener.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/WorkItemManager.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/ProcessInstanceImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/VariableScopeInstanceImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/WorkItemImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/demo/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/demo/DoNothingWorkItemHandler.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/demo/SystemOutWorkItemHandler.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/demo/UIWorkItemHandler.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/demo/UIWorkItemHandlerDialog.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/AccumulateNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/AlphaNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/BetaMemory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/BetaNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ClassObjectTypeConf.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/CollectNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/CompositeObjectSinkAdapter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/CompositeTupleSinkAdapter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/EmptyObjectSinkAdapter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/EmptyTupleSinkAdapter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/EntryPointNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/EvalConditionNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ExistsNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/FactHandleMemory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/FactTemplateTypeConf.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/FromNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/InitialFactHandle.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/InitialFactImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/JoinNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/LIANodePropagation.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/LeftInputAdapterNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/MemoryVisitor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/NotNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectSink.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectSinkNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectSinkNodeList.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectSinkPropagator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectSource.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectTypeConf.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectTypeNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/PropagationQueuingNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/QueryTerminalNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/Rete.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteStatelessSessionResult.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteTuple.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooBuilder.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooFactHandleFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooRuleBase.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooStatefulSession.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooStatelessSession.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooTemporalSession.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooWorkingMemory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/RightInputAdapterNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/RuleTerminalNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/SingleObjectSinkAdapter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/SingleTupleSinkAdapter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/Sink.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TerminalNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TimeWindowNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleMemory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleSink.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleSinkNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleSinkNodeList.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleSinkPropagator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleSource.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/AccumulateBuilder.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/BuildContext.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/BuildUtils.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/CollectBuilder.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/EntryPointBuilder.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/EvalBuilder.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/ForallBuilder.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/FromBuilder.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/GroupElementBuilder.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/PatternBuilder.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/ReteooComponentBuilder.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/ReteooRuleBuilder.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/TimeWindowBuilder.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/AbstractCompositeConstraint.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/AbstractCompositeRestriction.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Accumulate.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/AndCompositeRestriction.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/AndConstraint.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Collect.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/CompositePackageClassLoader.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/ConditionalElement.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/ContextEntry.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Declaration.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Dialectable.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/DroolsClassLoader.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/DuplicateRuleNameException.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/EntryPoint.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/EvalCondition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/FixedDuration.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Forall.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/From.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/GroupElement.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/GroupElementFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/ImportDeclaration.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/InvalidPatternException.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/InvalidRuleException.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/InvalidRulePackage.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/LineMappings.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/LiteralConstraint.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/LiteralRestriction.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/LogicTransformer.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/MapBackedClassLoader.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/MultiRestrictionFieldConstraint.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/NoConsequenceException.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/OrCompositeRestriction.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/OrConstraint.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Package.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/PackageCompilationData.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Pattern.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/PatternSource.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/PredicateConstraint.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Query.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/ReturnValueConstraint.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/ReturnValueRestriction.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Rule.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/RuleConditionElement.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/RuleConstructionException.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/TimeMachine.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/TimeWindow.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/TypeDeclaration.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/VariableConstraint.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/VariableRestriction.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/common/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/core/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/core/RuleFlowProcess.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/core/validation/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/core/validation/RuleFlowProcessValidator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/instance/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/instance/RuleFlowProcessInstance.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/instance/RuleFlowProcessInstanceFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/instance/impl/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/instance/impl/factories/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Accumulator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Action.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Activation.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ActivationGroup.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/AgendaFilter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/AgendaGroup.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/AlphaNodeFieldConstraint.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/AsyncExceptionHandler.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/BetaNodeFieldConstraint.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/CompiledInvoker.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ConflictResolver.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Consequence.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ConsequenceException.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ConsequenceExceptionHandler.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Constraint.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/DataProvider.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/DeclarationScopeResolver.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Duration.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/EvalExpression.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Evaluator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ExecutorServiceFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Extractor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/FactHandleFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/FieldExtractor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/FieldValue.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/FunctionResolver.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Functions.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/GlobalExporter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/GlobalExtractor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/GlobalResolver.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Invoker.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/JavaFact.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/KnowledgeHelper.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ObjectType.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/PatternExtractor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/PredicateExpression.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/PropagationContext.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Restriction.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ReturnValueEvaluator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ReturnValueExpression.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/RuleBaseUpdateListener.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/RuleBaseUpdateListenerFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/RuleComponent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/RuleFlowGroup.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Salience.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Tuple.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/AbstractSessionClock.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/EventExpiration.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/GlobalSessionClockImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/SessionClock.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/SessionPseudoClock.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/SessionSystemClock.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/AbstractBaseLinkedListNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/AbstractHashTable.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ArrayUtils.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/BinaryHeapQueue.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/BinaryRuleBaseLoader.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ChainedProperties.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ClassUtils.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/CompositeCollection.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ConfFileUtils.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/DateUtils.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/Entry.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/FactEntry.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/FactHandleIndexHashTable.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/FactHashTable.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/FactList.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/Iterator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/IteratorChain.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/JavaIteratorAdapter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/LinkedList.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/LinkedListEntry.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/LinkedListNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ObjectHashMap.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ObjectHashSet.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/OrderedFactHashTable.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/OrderedTupleHashTable.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/PrimitiveLongMap.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/PrimitiveLongStack.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/Queue.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/Queueable.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ReflectiveVisitor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ShadowProxyUtils.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/StringUtils.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ThreadSafeJavaIteratorAdapter.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/TupleHashTable.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/TupleIndexHashTable.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/UUID.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/UUIDGenerator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/asm/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/asm/ClassFieldInspector.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/asm/FieldAccessor.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/asm/FieldAccessorMap.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/asm/MethodComparator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/Connection.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/Constraint.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/Node.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/NodeContainer.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/WorkflowProcess.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/ConnectionImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/ConstraintImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/DroolsConsequenceAction.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/NodeContainerImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/NodeImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/WorkflowProcessImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/ActionNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/CompositeNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/EndNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/Join.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/MilestoneNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/RuleSetNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/SequenceNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/Split.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/StartNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/SubProcessNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/WorkItemNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/NodeInstance.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/NodeInstanceContainer.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/WorkflowProcessInstance.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/ConstraintEvaluator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/NodeInstanceFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/NodeInstanceFactoryRegistry.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/NodeInstanceImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/ReturnValueConstraintEvaluator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/RuleConstraintEvaluator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/WorkflowProcessInstanceImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/factory/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/factory/CreateNewNodeFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/factory/ReuseNodeFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/ActionNodeInstance.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/CompositeNodeInstance.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/EndNodeInstance.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/JoinInstance.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/MilestoneNodeInstance.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/RuleSetNodeInstance.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/SplitInstance.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/StartNodeInstance.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/SubProcessNodeInstance.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/WorkItemNodeInstance.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/META-INF/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/META-INF/drools.default.rulebase.conf
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/audit/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/audit/package.html
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/event/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/event/package.html
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/package.html
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/rule/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/rule/package.html
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/visualize/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/visualize/package.html
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/overview.html
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/codehaus/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/codehaus/jfdi/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/codehaus/jfdi/interpreter/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/codehaus/jfdi/interpreter/ClassTypeResolverTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/Address.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/Cheese.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/CheeseEqual.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/CheeseInterface.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/DroolsTestCase.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/FirstClass.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/MockFactHandle.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/Person.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/RuleBaseConfigurationTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/RuleBaseFactoryTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/RuleIntegrationExceptionTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/SecondClass.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/TestWorkingMemoryEventListener.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/DirectoryScannerTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/FileScannerTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/MockListener.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/MockProvider.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/MockRuleAgent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/RuleAgentTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/RuleBaseAssemblerTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/URLScannerTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/BaseClassFieldExtractorFactoryTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/ClassFieldExtractorTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/ConcreteChild.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/DelegateJavaFactHandlerTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/EvaluatorFactoryTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/FieldFactoryTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/FieldValueTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/ShadowProxyFactoryTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/TemporalEvaluatorFactoryTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/TestBean.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/ValueTypeTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/dataproviders/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/dataproviders/TestVariable.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/BaseClassFieldExtractorsTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/BooleanClassFieldExtractorTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/ByteClassFieldExtractorTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/CharClassFieldExtractorTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/DoubleClassFieldExtractorTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/FloatClassFieldExtractorTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/IntClassFieldExtractorTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/LongClassFieldExtractorTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/MVELClassFieldExtractorTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/ObjectClassFieldExtractorTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/ShortClassFieldExtractorTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/mvel/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/mvel/MVELCalendarCoercionTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/mvel/MVELDateCoercionTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/BaseBetaConstraintsTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/DefaultBetaConstraintsTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/DoubleBetaConstraintsTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/EqualityKeyTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/QuadroupleBetaConstraintsTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/SequentialAgendaTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/SingleBetaConstraintsTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/TripleBetaConstraintsTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/event/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/event/AgendaEventSupportTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/event/RuleBaseEventListenerTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/event/WorkingMemoryEventSupportTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/BaseMannersTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Chosen.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Context.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Count.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Guest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Hobby.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/LastSeat.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Path.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/ReteooMannersTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Seating.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Sex.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/model/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/facttemplates/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/facttemplates/FactTemplateFieldExtractorTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/facttemplates/FactTemplateTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/facttemplates/FieldTemplateTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/AccumulateNodeTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/AddRemoveTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/AgendaTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/AlphaNodeTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/BaseNodeTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/BetaNodeTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/CollectNodeTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/CompositeObjectSinkAdapterTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/CrossProductTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/DefaultFactHandleFactoryTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/EvalConditionNodeTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ExistsNodeTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/FactHandleTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/FromNodeTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/InstrumentedReteTuple.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/JoinNodeTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/LeftInputAdapterNodeTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/LogicalAssertionTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockAccumulator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockEvalCondition.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockObjectSink.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockObjectSource.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockTupleSink.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockTupleSource.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/NotNodeTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ObjectSourceTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ObjectTypeConfTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ObjectTypeNodeTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/OtherwiseTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/PropertyChangeListenerTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/QueryTerminalNodeTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ReteTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ReteooBuilderTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ReteooRuleBaseTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ReteooWorkingMemoryTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/RuleFlowGroupTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/SchedulerTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/TupleSourceTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/builder/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/builder/ReteooRuleBuilderTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/DeclarationTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/FieldConstraintTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/FixedDurationTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/GroupElementTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/LogicTransformerTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/PackageCompilationDataTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/PatternTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/RuleTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/spi/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/spi/MockConstraint.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/spi/MockObjectType.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/BaseQueueable.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/BinaryHeapPriorityQueueTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/ClassUtilsTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/FactHashTableTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/FieldIndexEntryTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/FieldIndexHashTableTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/LinkedListTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/LongQueueable.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/NaturalComparator.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/ObjectHashMapTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/ObjectHashMapTest2.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/PrimitiveLongMapTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/ShadowProxyUtilsTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/AbstractClass.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/BaseBean.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/BeanInherit.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/ClassFieldInspectorTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/InterfaceChild.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/InterfaceChildImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/InterfaceParent.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/InterfaceParent2.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/MethodCompareA.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/MethodCompareB.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/MethodComparerTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestAbstract.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestAbstractImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestBean.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestInterface.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestInterfaceImpl.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestObject.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/EndNodeInstanceTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/MockNode.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/MockNodeInstance.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/MockNodeInstanceFactory.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/ProcessNodeInstanceFactoryTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/StartNodeInstanceTest.java
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/META-INF/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/META-INF/mockProcessNodeInstanceFactory.conf
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/correct_processTree1.dat
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/correct_transform1.dat
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners128.dat
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners16.dat
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners32.dat
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners5.dat
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners64.dat
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners8.dat
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/rule-agent-config.properties
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/sample-agent-config.properties
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/waltz12.dat
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/target/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/target/classes/
   labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/target/test-classes/
Log:
Initial import.

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/.classpath
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/.classpath	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/.classpath	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src/main/java"/>
+	<classpathentry excluding="**/*.java" kind="src" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**/*.java" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Drools Developer Library"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/.project
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/.project	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/.project	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>drools-core</name>
+	<comment>A rule production system</comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.drools.eclipse.droolsbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/build.properties
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/build.properties	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/build.properties	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,14 @@
+bin.includes = META-INF/,\
+               icons/,\
+               lib/,\
+               drools-core.jar
+src.includes = META-INF/,\
+               build.properties,\
+               .classpath,\
+               .project,\
+               icons/
+jars.compile.order = drools-core.jar
+source.drools-core.jar = src/main/java/
+output.drools-core.jar = target/classes/
+jars.extra.classpath = lib/drools-asm-2.2.1.jar,\
+                       lib/xstream-1.1.3.jar

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/pom.xml
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/pom.xml	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/pom.xml	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <artifactId>drools</artifactId>
+    <groupId>org.drools</groupId>
+    <version>4.1.0.SNAPSHOT</version>
+  </parent>
+
+  <artifactId>drools-core</artifactId>
+  <packaging>jar</packaging>
+  <name>Drools :: Rete-OO Core</name>
+
+  <repositories>
+    <repository>
+      <id>basedir</id>
+      <url>file://${basedir}/../m2_repo</url>
+    </repository>
+  </repositories>  
+  
+  <dependencies>  
+    <!-- following are required for parser (lang). May be refactored out of core module. -->
+    <dependency>
+      <groupId>com.thoughtworks.xstream</groupId>
+      <artifactId>xstream</artifactId>
+      <optional>true</optional>
+    </dependency>
+
+    <dependency>
+      <groupId>org.mvel</groupId>
+      <artifactId>mvel</artifactId>
+    </dependency>     
+    
+  </dependencies>
+  
+  <build>
+    <plugins>
+      
+    <plugin>
+      <groupId>org.apache.maven.plugins</groupId>
+      <artifactId>maven-surefire-plugin</artifactId>
+      <configuration>
+        <includes>
+          <include>**/*Test.java</include>
+        </includes>
+        <!--excludes>
+          <exclude>**/LogicTransformerTest.java</exclude>
+          <exclude>**/LeapsMannersTest.java</exclude>          
+          <exclude>**/ReteooMannersTest.java</exclude>                    
+          <exclude>**/LeapsWaltzTest.java</exclude>          
+          <exclude>**/ReteooWaltzTest.java</exclude>             
+          <exclude>**/TableTest.java</exclude>                       
+        </excludes-->
+      </configuration>
+    </plugin>      
+    </plugins>
+  </build>
+
+
+</project>

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/Agenda.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/Agenda.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/Agenda.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,138 @@
+package org.drools;
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.Activation;
+import org.drools.spi.ActivationGroup;
+import org.drools.spi.AgendaGroup;
+import org.drools.spi.RuleFlowGroup;
+
+/**
+ * Agenda interface for the WorkingMemory
+ *
+ */
+public interface Agenda {
+
+    /**
+     * Returns the WorkignMemory for this Agenda
+     * @return
+     *      The WorkingMemory
+     */
+    public WorkingMemory getWorkingMemory();
+
+    /**
+     * Sets the Agenda's focus to the specified AgendaGroup
+     * @param agendaGroup
+     * @return
+     */
+    public boolean setFocus(AgendaGroup agendaGroup);
+
+    /**
+     * Sets the Agenda's focus to the specified AgendaGroup
+     * @param agendaGroup
+     * @return
+     */    
+    public void setFocus(String name);
+
+    public AgendaGroup getFocus();
+
+    public AgendaGroup getAgendaGroup(String name);
+
+    public RuleFlowGroup getRuleFlowGroup(String name);
+
+    /**
+     * Activates the <code>RuleFlowGroup</code> with the given name.
+     * All activations in the given <code>RuleFlowGroup</code> are added to the agenda.
+     * As long as the <code>RuleFlowGroup</code> remains active,
+     * its activations are automatically added to the agenda. 
+     */
+    public void activateRuleFlowGroup(String name);
+
+    /**
+     * Deactivates the <code>RuleFlowGroup</code> with the given name.
+     * All activations in the given <code>RuleFlowGroup</code> are removed from the agenda.
+     * As long as the <code>RuleFlowGroup</code> remains deactive,
+     * its activations are not added to the agenda
+     */
+    public void deactivateRuleFlowGroup(String name);
+
+    public AgendaGroup[] getAgendaGroups();
+
+    public AgendaGroup[] getStack();
+
+    public ActivationGroup getActivationGroup(String name);
+
+    /**
+     * Iterates all the <code>AgendGroup<code>s in the focus stack returning the total number of <code>Activation</code>s
+     * @return
+     *      total number of <code>Activation</code>s on the focus stack
+     */
+    public int focusStackSize();
+
+    /**
+     * Iterates all the modules in the focus stack returning the total number of <code>Activation</code>s
+     * @return
+     *      total number of activations on the focus stack
+     */
+    public int agendaSize();
+
+    public Activation[] getActivations();
+
+    public Activation[] getScheduledActivations();
+
+    /**
+     * Clears all Activations from the Agenda
+     * 
+     */
+    public void clearAgenda();
+
+    /**
+     * Clears all Activations from an Agenda Group. Any Activations that are also in an Xor Group are removed the
+     * the Xor Group.
+     * 
+     * @param agendaGroup
+     */
+    public void clearAgendaGroup(String name);
+
+    /**
+     * Clears all Activations from an Agenda Group. Any Activations that are also in an Xor Group are removed the
+     * the Xor Group.
+     * 
+     * @param agendaGroup
+     */
+    public void clearAgendaGroup(AgendaGroup agendaGroup);
+
+    /**
+     * Clears all Activations from an Activation-Group. Any Activations that are also in an Agenda Group are removed
+     * from the Agenda Group.
+     * 
+     * @param activationGroup
+     */
+    public void clearActivationGroup(String name);
+
+    /**
+     * Clears all Activations from an Activation Group. Any Activations that are also in an Agenda Group are removed
+     * from the Agenda Group.
+     * 
+     * @param activationGroup
+     */
+    public void clearActivationGroup(ActivationGroup activationGroup);
+    
+    public void clearRuleFlowGroup(final String name);
+    
+    public void clearRuleFlowGroup(final RuleFlowGroup ruleFlowGroup);
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/CheckedDroolsException.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/CheckedDroolsException.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/CheckedDroolsException.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,70 @@
+package org.drools;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Base RuntimeException<code>drools Logic Engine</code> exception.
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ */
+public class CheckedDroolsException extends Exception {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    /**
+     * @see java.lang.Exception#Exception()
+     */
+    public CheckedDroolsException() {
+        super();
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(String message)
+     */
+    public CheckedDroolsException(final String message) {
+        super( message );
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(String message, Throwable cause)
+     */
+    public CheckedDroolsException(final String message,
+                                  final Throwable cause) {
+        super( message );
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(Throwable cause)
+     */
+    public CheckedDroolsException(final Throwable cause) {
+        super( cause );
+    }
+
+    /**
+     * Get the root cause, if any.
+     * 
+     * @deprecated Use Throwable.getCause()
+     * @return The root cause of this exception, as a <code>Throwable</code>,
+     *         if this exception has a root cause, else <code>null</code>.
+     */
+    public Throwable getRootCause() {
+        return super.getCause();
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ClockType.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ClockType.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ClockType.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Nov 29, 2007
+ */
+package org.drools;
+
+import org.drools.temporal.AbstractSessionClock;
+import org.drools.temporal.SessionPseudoClock;
+import org.drools.temporal.SessionSystemClock;
+
+/**
+ * This enum represents all engine supported clocks
+ * 
+ * @author mgroch
+ */
+public enum ClockType {
+
+	  /**
+	   * A System clock is a clock that returns the time based on the underlying
+	   * system clock. It is usually used for real time applications
+	   */
+	  SYSTEM_CLOCK {
+		  public SessionSystemClock createInstance() {
+	          return new SessionSystemClock();
+	    	  //return SessionSystemClock.getInstance();
+	      }
+	  },
+	  
+	  /**
+	   * A Pseudo clock is a clock that is completely controlled by the
+	   * client application. It is usually used during simulations or tests
+	   */
+	  PSEUDO_CLOCK {
+	      public SessionPseudoClock createInstance() {
+	          return new SessionPseudoClock();
+	    	  //return SessionPseudoClock.getInstance();
+	      }
+	  };
+	  
+	  public abstract AbstractSessionClock createInstance();
+	  
+	}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/EntryPointInterface.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/EntryPointInterface.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/EntryPointInterface.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 14, 2007
+ */
+package org.drools;
+
+import java.io.Serializable;
+
+/**
+ * An interface for instances that allow handling of entry-point-scoped
+ * facts
+ *  
+ * @author etirelli
+ */
+public interface EntryPointInterface
+    extends
+    Serializable {
+    
+    /**
+     * Assert a fact.
+     * 
+     * @param object
+     *            The fact object.
+     * 
+     * @return The new fact-handle associated with the object.
+     * 
+     * @throws FactException
+     *             If a RuntimeException error occurs.
+     */
+    FactHandle insert(Object object) throws FactException;
+
+    /**
+     * Insert a fact registering JavaBean <code>PropertyChangeListeners</code>
+     * on the Object to automatically trigger <code>update</code> calls
+     * if <code>dynamic</code> is <code>true</code>.
+     * 
+     * @param object
+     *            The fact object.
+     * @param dynamic
+     *            true if Drools should add JavaBean
+     *            <code>PropertyChangeListeners</code> to the object.
+     * 
+     * @return The new fact-handle associated with the object.
+     * 
+     * @throws FactException
+     *             If a RuntimeException error occurs.
+     */
+    FactHandle insert(Object object,
+                            boolean dynamic) throws FactException;
+
+    /**
+     * Retract a fact.
+     * 
+     * @param handle
+     *            The fact-handle associated with the fact to retract.
+     * 
+     * @throws FactException
+     *             If a RuntimeException error occurs.
+     */
+    void retract(FactHandle handle) throws FactException;
+
+    /**
+     * Inform the WorkingMemory that a Fact has been modified and that it
+     * should now update the network.
+     * 
+     * @param handle
+     *            The fact-handle associated with the fact to modify.
+     * @param object
+     *            The new value of the fact.
+     * 
+     * @throws FactException
+     *             If a RuntimeException error occurs.
+     */
+    void update(FactHandle handle,
+                      Object object) throws FactException;
+    
+    /**
+     * 
+     * @param factHandle
+     */
+    public void modifyRetract(final FactHandle factHandle);
+    
+    /**
+     * 
+     * @param factHandle
+     * @param object
+     */
+    public void modifyInsert(final FactHandle factHandle,
+                             final Object object);    
+
+    
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/FactException.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/FactException.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/FactException.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,58 @@
+package org.drools;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Base exception indicating an error in manipulating facts.
+ * 
+ */
+public class FactException extends RuntimeDroolsException {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    /**
+     * @see java.lang.Exception#Exception()
+     */
+    public FactException() {
+        super();
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(String message)
+     */
+    public FactException(final String message) {
+        super( message );
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(String message, Throwable cause)
+     */
+    public FactException(final String message,
+                         final Throwable cause) {
+        super( message,
+               cause );
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(Throwable cause)
+     */
+    public FactException(final Throwable cause) {
+        super( cause );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/FactHandle.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/FactHandle.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/FactHandle.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,39 @@
+package org.drools;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Persistent handle to an asserted fact.
+ *
+ * @see WorkingMemory#assertObject
+ *
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter </a>
+ */
+
+import java.io.Serializable;
+
+public interface FactHandle
+    extends
+    Serializable {
+
+    /**
+     * Convert this handle to an external representation.
+     * 
+     * @return The external string form.
+     */
+    String toExternalForm();
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/InitialFact.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/InitialFact.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/InitialFact.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,29 @@
+package org.drools;
+
+import java.io.Serializable;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Initial fact, automatically put into the network. This fact is needed by 'not' CEs
+ * when they are the CEs in the rule.
+ */
+public interface InitialFact
+    extends
+    Serializable {
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/IntegrationException.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/IntegrationException.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/IntegrationException.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,53 @@
+package org.drools;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class IntegrationException extends CheckedDroolsException {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    /**
+     * @see java.lang.Exception#Exception()
+     */
+    public IntegrationException() {
+        super();
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(String message)
+     */
+    public IntegrationException(final String message) {
+        super( message );
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(String message, Throwable cause)
+     */
+    public IntegrationException(final String message,
+                                final Throwable cause) {
+        super( message );
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(Throwable cause)
+     */
+    public IntegrationException(final Throwable cause) {
+        super( cause );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ObjectFilter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ObjectFilter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ObjectFilter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,16 @@
+package org.drools;
+
+/**
+ * ObjectFilter is used with WorkingMemories to filter out instances during Iteration
+ * @author mproctor
+ *
+ */
+public interface ObjectFilter {
+    
+    /**
+     * Returning true means the Iterator accepts, and thus returns, the current Object.
+     * @param object
+     * @return
+     */
+    boolean accept(Object object);
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/Otherwise.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/Otherwise.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/Otherwise.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,13 @@
+package org.drools;
+
+/**
+ * This class is essentually a named fact that will be asserted when the engine
+ * has not matched any rules.
+ * 
+ * This class is not currently used.
+ * 
+ *
+ */
+public class Otherwise {
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/PackageIntegrationException.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/PackageIntegrationException.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/PackageIntegrationException.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,85 @@
+package org.drools;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.rule.Package;
+
+/**
+ * Indicates an error integrating a <code>Package</code> into a
+ * <code>RuleBase</code>.
+ * 
+ * @see RuleBase#addRule
+ * @see RuleBase#addPackage
+ * 
+ */
+public class PackageIntegrationException extends IntegrationException {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+    /** The rule. */
+    private final Package     pkg;
+
+    /**
+     * @see java.lang.Exception#Exception()
+     * 
+     * @param pkg
+     *            The offending rule.
+     */
+    public PackageIntegrationException(final String message,
+                                       final Package pkg) {
+        super( message );
+        this.pkg = pkg;
+    }
+
+    /**
+     * @see java.lang.Exception#Exception()
+     * 
+     * @param pkg
+     *            The offending rule.
+     */
+    public PackageIntegrationException(final Package pkg) {
+        super( createMessage( pkg ) );
+        this.pkg = pkg;
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(Throwable cause)
+     * 
+     * @param pkg
+     *            The offending rule.
+     */
+    public PackageIntegrationException(final Package pkg,
+                                       final Throwable cause) {
+        super( createMessage( pkg ),
+               cause );
+        this.pkg = pkg;
+    }
+
+    /**
+     * Retrieve the <code>Package</code>.
+     * 
+     * @return The pkg
+     */
+    public Package getPackage() {
+        return this.pkg;
+    }
+
+    private static String createMessage(final Package pkg) {
+        return pkg.getName() + " cannot be integrated";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ProcessIntegrationException.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ProcessIntegrationException.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ProcessIntegrationException.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,78 @@
+package org.drools;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.process.core.Process;
+import org.drools.rule.Rule;
+
+/**
+ * Indicates an error integrating a <code>Process</code> or <code>Package</code>
+ * into a <code>RuleBase</code>.
+ * 
+ * @see RuleBase#addProcess
+ * @see RuleBase#addPackage
+ * 
+ * @author <a href="mailto:bob at eng.werken.com">bob mcwhirter </a>
+ * 
+ * @version $Id: RuleIntegrationException.java,v 1.6 2004/09/17 00:14:06
+ *          mproctor Exp $
+ */
+public class ProcessIntegrationException extends IntegrationException {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+    /** The rule. */
+    private final    Process    process;
+
+    /**
+     * @see java.lang.Exception#Exception()
+     * 
+     * @param process
+     *            The offending process.
+     */
+    public ProcessIntegrationException(final Process process) {
+        super( createMessage( process ) );
+        this.process = process;
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(Throwable cause)
+     * 
+     * @param rule
+     *            The offending rule.
+     */
+    public ProcessIntegrationException(final Process process,
+                                    final Throwable cause) {
+        super( createMessage( process ),
+               cause );
+        this.process = process;
+    }
+
+    /**
+     * Retrieve the <code>Rule</code>.
+     * 
+     * @return The rule.
+     */
+    public Process getProcess() {
+        return this.process;
+    }
+
+    private static String createMessage(final Process process) {
+        return process.getName() + " cannot be integrated";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/QueryResult.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/QueryResult.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/QueryResult.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,121 @@
+package org.drools;
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Map;
+
+import org.drools.base.ShadowProxy;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.Declaration;
+import org.drools.spi.Tuple;
+
+public class QueryResult {
+
+    protected Tuple       tuple;
+    private WorkingMemory workingMemory;
+    private QueryResults  queryResults;
+
+    public QueryResult(final Tuple tuple,
+                       final WorkingMemory workingMemory,
+                       final QueryResults queryResults) {
+        this.tuple = tuple;
+        this.workingMemory = workingMemory;
+        this.queryResults = queryResults;
+    }
+
+    /**
+     * Return a map of Declarations where the key is the identifier and the value
+     * is the Declaration.
+     * 
+     * @return
+     *      The Map of Declarations.
+     */    
+    public Map getDeclarations() {
+        return this.queryResults.getDeclarations();
+    }
+
+    /**
+     * Returns the Object for int position in the Tuple
+     * 
+     * @param i
+     * @return
+     *     The Object
+     */
+    public Object get(final int i) {
+        //adjust for the DroolsQuery object
+        return getObject( this.tuple.get( i + 1 ));
+    }
+
+    /** 
+     * Return the Object for the given Declaration identifer.
+     * @param identifier
+     * @return
+     *      The Object
+     */
+    public Object get(final String identifier) {
+        return get( (Declaration) this.queryResults.getDeclarations().get( identifier ) );
+    }
+
+    /** 
+     * Return the Object for the given Declaration.
+     * @param identifier
+     * @return
+     *      The Object
+     */    
+    public Object get(final Declaration declaration) {
+        return declaration.getValue( (InternalWorkingMemory) workingMemory, getObject( this.tuple.get( declaration ) ) );
+    }
+
+    /**
+     * Return the FactHandles for the Tuple.
+     * @return
+     */
+    public FactHandle[] getFactHandles() {
+        // Strip the DroolsQuery fact
+        final FactHandle[] src = this.tuple.getFactHandles();
+        final FactHandle[] dst = new FactHandle[src.length - 1];
+        System.arraycopy( src,
+                          1,
+                          dst,
+                          0,
+                          dst.length );
+        return dst;
+    }
+
+    /**
+     * The size of the Tuple; i.e. the number of columns (FactHandles) in this row result.
+     * @return
+     */
+    public int size() {
+        // Adjust for the DroolsQuery object
+        return this.tuple.getFactHandles().length - 1;
+    }
+    
+    /**
+     * Get the Object for the given FactHandle
+     * @param handle
+     * @return
+     */
+    private Object getObject(FactHandle factHandle) {
+        InternalFactHandle handle = ( InternalFactHandle ) factHandle; 
+        if ( handle.isShadowFact() ) {
+            return ((ShadowProxy) handle.getObject()).getShadowedObject();
+        } else {
+            return handle.getObject();
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/QueryResults.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/QueryResults.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/QueryResults.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,119 @@
+package org.drools;
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import org.drools.rule.Declaration;
+import org.drools.rule.Query;
+import org.drools.spi.Tuple;
+
+/**
+ * Returned QueryResults instance for a requested named query. from here you can iterate the returned data, or
+ * get a specific row. All the available Declarations used in the query can also be accessed.
+ *
+ */
+public class QueryResults {
+    private Query           query;
+
+    private Map             declarations;
+
+    protected List          results;
+    protected WorkingMemory workingMemory;
+
+    public QueryResults(final List results,
+                        final Query query,
+                        final WorkingMemory workingMemory) {
+        this.results = results;
+        this.query = query;
+        this.workingMemory = workingMemory;
+    }
+
+    public QueryResult get(final int i) {
+        if ( i > this.results.size() ) {
+            throw new NoSuchElementException();
+        }
+        return new QueryResult( (Tuple) this.results.get( i ),
+                                this.workingMemory,
+                                this );
+    }
+
+    /**
+     * Returns an Iterator for the results.
+     * 
+     * @return
+     */
+    public Iterator iterator() {
+        return new QueryResultsIterator( this.results.iterator() );
+    }
+
+    /**
+     * Return a map of Declarations where the key is the identifier and the value
+     * is the Declaration.
+     * 
+     * @return
+     *      The Map of Declarations.
+     */
+    public Map getDeclarations() {
+
+        final Declaration[] declarations = this.query.getDeclarations();
+        final Map map = new HashMap( declarations.length );
+        for ( int i = 0, length = declarations.length; i < length; i++ ) {
+            map.put( declarations[i].getIdentifier(),
+                     declarations[i] );
+        }
+        this.declarations = map;
+
+        return this.declarations;
+    }
+
+    /**
+     * The results size
+     * @return
+     */
+    public int size() {
+        return this.results.size();
+    }
+
+    private class QueryResultsIterator
+        implements
+        Iterator {
+        private Iterator iterator;
+
+        public QueryResultsIterator(final Iterator iterator) {
+            this.iterator = iterator;
+        }
+
+        public boolean hasNext() {
+            return this.iterator.hasNext();
+        }
+
+        public Object next() {
+            return new QueryResult( (Tuple) this.iterator.next(),
+                                    QueryResults.this.workingMemory,
+                                    QueryResults.this );
+        }
+
+        public void remove() {
+            this.iterator.remove();
+        }
+
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuleBase.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuleBase.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuleBase.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,214 @@
+package org.drools;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.util.Observer;
+import java.util.Set;
+
+import org.drools.rule.Package;
+
+/**
+ * Active collection of <code>Rule</code>s.
+ * 
+ * <p>
+ * From a <code>RuleBase</code> many <code>WorkingMemory</code> rule
+ * sessions may be instantiated. Additionally, it may be inspected to determine
+ * which <code>Package</code> s it contains.
+ * </p>
+ * 
+ * @see WorkingMemory
+ */
+public interface RuleBase
+    extends
+    Serializable,
+    RuleBaseEventManager {
+
+    public static final int RETEOO = 1;
+
+    StatelessSession newStatelessSession();
+
+    /**
+     * Create a new <code>WorkingMemory</code> session for this
+     * <code>RuleBase</code>. By default the RuleBase retains a
+     * weak reference to returned WorkingMemory.
+     * 
+     * <p>
+     * The created <code>WorkingMemory</code> uses the default conflict
+     * resolution strategy.
+     * </p>
+     * 
+     * @see WorkingMemory
+     * @see org.drools.conflict.DefaultConflictResolver
+     * 
+     * @return A newly initialized <code>WorkingMemory</code>.
+     */
+    StatefulSession newStatefulSession();
+
+    /**
+     * Create a new <code>WorkingMemory</code> session for this
+     * <code>RuleBase</code>. Optionally the RuleBase retains a
+     * weak reference to returned WorkingMemory.
+     * 
+     * <p>
+     * The created <code>WorkingMemory</code> uses the default conflict
+     * resolution strategy.
+     * </p>
+     * 
+     * @see WorkingMemory
+     * @see org.drools.conflict.DefaultConflictResolver
+     * 
+     * @return A newly initialized <code>WorkingMemory</code>.
+     */
+    StatefulSession newStatefulSession(boolean keepReference);
+
+    /**
+     * RuleBases handle the returning of a Serialized WorkingMemory
+     * pass as an InputStream. If the reference is a byte[] then
+     * wrap with new ByteArrayInputStream. By default the RuleBase retains a
+     * weak reference to returned WorkingMemory.
+     * 
+     * <p>
+     * The created <code>WorkingMemory</code> uses the default conflict
+     * resolution strategy.
+     * </p>
+     * 
+     * @see WorkingMemory
+     * @see org.drools.conflict.DefaultConflictResolver
+     * 
+     * @return A serialised initialized <code>WorkingMemory</code>.
+     */
+    StatefulSession newStatefulSession(InputStream stream) throws IOException,
+                                                          ClassNotFoundException;
+    
+    /**
+     * Creates a new temporal session using the defined clock type.
+     * 
+     * @param clockType
+     * @return
+     */
+    TemporalSession newTemporalSession(ClockType clockType);
+
+    /**
+     * Creates a new temporal session using the defined clock type.
+     * 
+     * @param keepReference maintains a reference in the rulebase to the created session
+     * @param clockType
+     * @return
+     */
+    TemporalSession newTemporalSession(boolean keepReference, ClockType clockType);
+    
+    /**
+     * RuleBases handle the returning of a Serialized WorkingMemory
+     * pass as an InputStream. If the reference is a byte[] then
+     * wrap with new ByteArrayInputStream. Optionally the RuleBase retains a
+     * weak reference to returned WorkingMemory.
+     * 
+     * <p>
+     * The created <code>WorkingMemory</code> uses the default conflict
+     * resolution strategy.
+     * </p>
+     * 
+     * @see WorkingMemory
+     * @see org.drools.conflict.DefaultConflictResolver
+     * 
+     * @return A serialised initialized <code>WorkingMemory</code>.
+     */
+    StatefulSession newStatefulSession(InputStream stream,
+                                       boolean keepReference) throws IOException,
+                                                             ClassNotFoundException;
+
+    Package[] getPackages();
+
+    Package getPackage(String name);
+
+    void addPackage(Package pkg) throws Exception;
+    
+    /**
+     * This locks the current RuleBase and all there referenced StatefulSessions. This should be 
+     * used when there is a number of dynamic RuleBase changes you wish to make, but cannot have any normal
+     * WorkingMemory operations occuring inbetween.
+     *
+     */
+    void lock();
+    
+    /**
+     * Unlocks the RuleBase and all of the referenced StatefulSessions.
+     *
+     */
+    void unlock();
+
+    /**
+     * Returns the number of additive operations applied since the last lock() was obtained 
+     * @return
+     */
+    int getAdditionsSinceLock();
+
+    /**
+     * Returns the number of removal operations applied since the last lock() was obtained 
+     * @return
+     */
+    int getRemovalsSinceLock();
+
+    /**
+     * Remove the package and all it's rules, functions etc
+     * @param packageName
+     */
+    void removePackage(String packageName);
+
+    /**
+     * Remove a specific Rule in a Package
+     * @param packageName
+     * @param ruleName
+     */
+    void removeRule(String packageName,
+                    String ruleName);
+
+    /**
+     * Removes a specific function in a specific package.
+     * @param packageName
+     * @param functionName
+     */
+    void removeFunction(String packageName,
+                        String functionName);
+
+    /**
+     * Removes a process by the process' id
+     * @param id
+     */
+    void removeProcess(String id);
+
+    /**
+     * Returns an array of all the referenced StatefulSessions
+     * @return
+     */
+    public StatefulSession[] getStatefulSessions();
+    
+    /**
+     * Returns an array of all the classes depending on (= observing) the temporal session clock
+     * @return
+     */
+    //public Set<Observer> getClockInitializedObservers();
+    
+    /**
+     * Adds an observer that wants to be notified when the session clock has been initialized
+     * @return
+     */
+    //public void addClockInitializedObserver(Observer myObserver);
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuleBaseConfiguration.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuleBaseConfiguration.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuleBaseConfiguration.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,805 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Map.Entry;
+
+import org.drools.common.AgendaGroupFactory;
+import org.drools.common.ArrayAgendaGroupFactory;
+import org.drools.common.PriorityQueueAgendaGroupFactory;
+import org.drools.spi.ConflictResolver;
+import org.drools.spi.ConsequenceExceptionHandler;
+import org.drools.temporal.SessionClock;
+import org.drools.temporal.SessionPseudoClock;
+import org.drools.util.ChainedProperties;
+import org.drools.util.ConfFileUtils;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.instance.impl.NodeInstanceFactory;
+import org.drools.workflow.instance.impl.NodeInstanceFactoryRegistry;
+import org.mvel.MVEL;
+
+/**
+ * RuleBaseConfiguration
+ * 
+ * A class to store RuleBase related configuration. It must be used at rule base instantiation time
+ * or not used at all.
+ * This class will automatically load default values from system properties, so if you want to set
+ * a default configuration value for all your new rule bases, you can simply set the property as 
+ * a System property.
+ * 
+ * After RuleBase is created, it makes the configuration immutable and there is no way to make it 
+ * mutable again. This is to avoid inconsistent behavior inside rulebase.
+ * 
+ * NOTE: This API is under review and may change in the future.
+ */
+
+/**
+ * drools.maintainTms = <true|false>
+ * drools.shadowproxy = <true|false> // sequentail=true always overrides setting this to false
+ * drools.shadowproxy.exclude = org.domainy.* org.domainx.ClassZ
+ * drools.sequential = <true|false>
+ * drools.sequential.agenda = <sequential|dynamic>
+ * drools.removeIdentities = <true|false>
+ * drools.shareAlphaNodes  = <true|false>
+ * drools.shareBetaNodes = <true|false>
+ * drools.alphaMemory <true/false>
+ * drools.alphaNodeHashingThreshold = <1...n>
+ * drools.compositeKeyDepth  =<1..3>
+ * drools.indexLeftBetaMemory = <true/false>
+ * drools.indexRightBetaMemory = <true/false>
+ * drools.assertBehaviour = <identity|equality>
+ * drools.logicalOverride = <discard|preserve>
+ * drools.executorService = <qualified class name>
+ * drools.conflictResolver = <qualified class name>
+ * drools.consequenceExceptionHandler = <qualified class name>
+ * drools.ruleBaseUpdateHandler = <qualified class name>
+ * drools.sessionClock = <qualified class name>
+ * 
+ */
+public class RuleBaseConfiguration
+    implements
+    Serializable {
+    private static final long                  serialVersionUID = 400L;
+
+    private ChainedProperties                  chainedProperties;
+
+    private boolean                            immutable;
+
+    private boolean                            sequential;
+    private SequentialAgenda                   sequentialAgenda;
+
+    private boolean                            maintainTms;
+    private boolean                            removeIdentities;
+    private boolean                            shareAlphaNodes;
+    private boolean                            shareBetaNodes;
+    private boolean                            alphaMemory;
+    private int                                alphaNodeHashingThreshold;
+    private int                                compositeKeyDepth;
+    private boolean                            indexLeftBetaMemory;
+    private boolean                            indexRightBetaMemory;
+    private AssertBehaviour                    assertBehaviour;
+    private LogicalOverride                    logicalOverride;
+    private String                             executorService;
+    private ConsequenceExceptionHandler        consequenceExceptionHandler;
+    private String                             ruleBaseUpdateHandler;
+    private Class< ? extends SessionClock>     sessionClockClass;
+
+    private ConflictResolver                   conflictResolver;
+
+    private boolean                            shadowProxy;
+    private Map                                shadowProxyExcludes;
+    private static final String                STAR             = "*";
+
+    private NodeInstanceFactoryRegistry processNodeInstanceFactoryRegistry;
+
+    private transient ClassLoader              classLoader;
+
+    /**
+     * Creates a new rulebase configuration using the provided properties
+     * as configuration options. Also, if a Thread.currentThread().getContextClassLoader()
+     * returns a non-null class loader, it will be used as the parent classloader
+     * for this rulebase class loaders, otherwise, the RuleBaseConfiguration.class.getClassLoader()
+     * class loader will be used.
+     *  
+     * @param properties
+     */
+    public RuleBaseConfiguration(Properties properties) {
+        init( null,
+              properties );
+    }
+
+    /**
+     * Creates a new rulebase with a default parent class loader set according
+     * to the following algorithm:
+     * 
+     * If a Thread.currentThread().getContextClassLoader() returns a non-null class loader, 
+     * it will be used as the parent class loader for this rulebase class loaders, otherwise, 
+     * the RuleBaseConfiguration.class.getClassLoader() class loader will be used.
+     *  
+     * @param properties
+     */
+    public RuleBaseConfiguration() {
+        init( null,
+              null );
+    }
+
+    /**
+     * A constructor that sets the parent classloader to be used
+     * while dealing with this rule base
+     * 
+     * @param classLoader
+     */
+    public RuleBaseConfiguration(ClassLoader classLoader) {
+        init( classLoader,
+              null );
+    }
+
+    /**
+     * A constructor that sets the classloader to be used as the parent classloader
+     * of this rule base classloaders, and the properties to be used
+     * as base configuration options
+     * 
+     * @param classLoder
+     * @param properties
+     */
+    public RuleBaseConfiguration(ClassLoader classLoader,
+                                 Properties properties) {
+        init( classLoader,
+              properties );
+    }
+
+    private void init(ClassLoader classLoader,
+                      Properties properties) {
+        this.immutable = false;
+
+        if ( classLoader != null ) {
+            this.classLoader = classLoader;
+        } else if ( Thread.currentThread().getContextClassLoader() != null ) {
+            this.classLoader = Thread.currentThread().getContextClassLoader();
+        } else {
+            this.classLoader = this.getClass().getClassLoader();
+        }
+
+        this.chainedProperties = new ChainedProperties( "rulebase.conf" );
+
+        if ( properties != null ) {
+            this.chainedProperties.addProperties( properties );
+        }
+
+        setSequentialAgenda( SequentialAgenda.determineSequentialAgenda( this.chainedProperties.getProperty( "drools.sequential.agenda",
+                                                                                                             "sequential" ) ) );
+
+        setSequential( Boolean.valueOf( this.chainedProperties.getProperty( "drools.sequential",
+                                                                            "false" ) ).booleanValue() );
+
+        setMaintainTms( Boolean.valueOf( this.chainedProperties.getProperty( "drools.maintainTms",
+                                                                             "true" ) ).booleanValue() );
+
+        setRemoveIdentities( Boolean.valueOf( this.chainedProperties.getProperty( "drools.removeIdentities",
+                                                                                  "false" ) ).booleanValue() );
+
+        setAlphaMemory( Boolean.valueOf( this.chainedProperties.getProperty( "drools.alphaMemory",
+                                                                             "false" ) ).booleanValue() );
+
+        setShareAlphaNodes( Boolean.valueOf( this.chainedProperties.getProperty( "drools.shareAlphaNodes",
+                                                                                 "true" ) ).booleanValue() );
+
+        setShareBetaNodes( Boolean.valueOf( this.chainedProperties.getProperty( "drools.shareBetaNodes",
+                                                                                "true" ) ).booleanValue() );
+
+        setAlphaNodeHashingThreshold( Integer.parseInt( this.chainedProperties.getProperty( "drools.alphaNodeHashingThreshold",
+                                                                                            "3" ) ) );
+
+        setCompositeKeyDepth( Integer.parseInt( this.chainedProperties.getProperty( "drools.compositeKeyDepth",
+                                                                                    "3" ) ) );
+
+        setIndexLeftBetaMemory( Boolean.valueOf( this.chainedProperties.getProperty( "drools.indexLeftBetaMemory",
+                                                                                     "true" ) ).booleanValue() );
+        setIndexRightBetaMemory( Boolean.valueOf( this.chainedProperties.getProperty( "drools.indexRightBetaMemory",
+                                                                                      "true" ) ).booleanValue() );
+
+        setAssertBehaviour( AssertBehaviour.determineAssertBehaviour( this.chainedProperties.getProperty( "drools.assertBehaviour",
+                                                                                                          "identity" ) ) );
+        setLogicalOverride( LogicalOverride.determineLogicalOverride( this.chainedProperties.getProperty( "drools.logicalOverride",
+                                                                                                          "discard" ) ) );
+
+        setExecutorService( this.chainedProperties.getProperty( "drools.executorService",
+                                                                "org.drools.concurrent.DefaultExecutorService" ) );
+
+        setConsequenceExceptionHandler( RuleBaseConfiguration.determineConsequenceExceptionHandler( this.chainedProperties.getProperty( "drools.consequenceExceptionHandler",
+                                                                                                                                        "org.drools.base.DefaultConsequenceExceptionHandler" ) ) );
+
+        setRuleBaseUpdateHandler( this.chainedProperties.getProperty( "drools.ruleBaseUpdateHandler",
+                                                                      "org.drools.base.FireAllRulesRuleBaseUpdateListener" ) );
+
+        setConflictResolver( RuleBaseConfiguration.determineConflictResolver( this.chainedProperties.getProperty( "drools.conflictResolver",
+                                                                                                                  "org.drools.conflict.DepthConflictResolver" ) ) );
+
+        // sequential mode always overrides and sets this to false
+        setShadowProxy( determineShadowProxy( this.chainedProperties.getProperty( "drools.shadowproxy",
+                                                                                  "true" ) ) );
+
+        setShadowProxyExcludes( this.chainedProperties.getProperty( "drools.shadowProxyExcludes",
+                                                                    "" ) );
+
+        setSessionClockClass( this.chainedProperties.getProperty( "drools.sessionClock",
+                                                                  SessionPseudoClock.class.getName() ) );
+
+    }
+
+    /**
+     * Makes the configuration object immutable. Once it becomes immutable, 
+     * there is no way to make it mutable again. 
+     * This is done to keep consistency.
+     */
+    public void makeImmutable() {
+        this.immutable = true;
+    }
+
+    /**
+     * Returns true if this configuration object is immutable or false otherwise.
+     * @return
+     */
+    public boolean isImmutable() {
+        return this.immutable;
+    }
+
+    private void checkCanChange() {
+        if ( this.immutable ) {
+            throw new UnsupportedOperationException( "Can't set a property after configuration becomes immutable" );
+        }
+    }
+
+    public void setSequential(boolean sequential) {
+        this.sequential = sequential;
+    }
+
+    public boolean isSequential() {
+        return this.sequential;
+    }
+
+    public boolean isMaintainTms() {
+        return this.maintainTms;
+    }
+
+    public void setMaintainTms(final boolean maintainTms) {
+        checkCanChange(); // throws an exception if a change isn't possible;
+        this.maintainTms = maintainTms;
+    }
+
+    public boolean isRemoveIdentities() {
+        return this.removeIdentities;
+    }
+
+    public void setRemoveIdentities(final boolean removeIdentities) {
+        checkCanChange(); // throws an exception if a change isn't possible;
+        this.removeIdentities = removeIdentities;
+    }
+
+    public boolean isAlphaMemory() {
+        return this.alphaMemory;
+    }
+
+    public void setAlphaMemory(final boolean alphaMemory) {
+        checkCanChange(); // throws an exception if a change isn't possible;
+        this.alphaMemory = alphaMemory;
+    }
+
+    public boolean isShareAlphaNodes() {
+        return this.shareAlphaNodes;
+    }
+
+    public void setShareAlphaNodes(final boolean shareAlphaNodes) {
+        checkCanChange(); // throws an exception if a change isn't possible;
+        this.shareAlphaNodes = shareAlphaNodes;
+    }
+
+    public boolean isShareBetaNodes() {
+        return this.shareBetaNodes;
+    }
+
+    public void setShareBetaNodes(final boolean shareBetaNodes) {
+        checkCanChange(); // throws an exception if a change isn't possible;
+        this.shareBetaNodes = shareBetaNodes;
+    }
+
+    public int getAlphaNodeHashingThreshold() {
+        return this.alphaNodeHashingThreshold;
+    }
+
+    public void setAlphaNodeHashingThreshold(final int alphaNodeHashingThreshold) {
+        checkCanChange(); // throws an exception if a change isn't possible;        
+        this.alphaNodeHashingThreshold = alphaNodeHashingThreshold;
+    }
+
+    public AssertBehaviour getAssertBehaviour() {
+        return this.assertBehaviour;
+    }
+
+    public void setAssertBehaviour(final AssertBehaviour assertBehaviour) {
+        checkCanChange(); // throws an exception if a change isn't possible;
+        this.assertBehaviour = assertBehaviour;
+    }
+
+    public int getCompositeKeyDepth() {
+        return this.compositeKeyDepth;
+    }
+
+    public void setCompositeKeyDepth(final int compositeKeyDepth) {
+        if ( !this.immutable ) {
+            if ( compositeKeyDepth > 3 ) {
+                throw new UnsupportedOperationException( "compositeKeyDepth cannot be greater than 3" );
+            }
+            this.compositeKeyDepth = compositeKeyDepth;
+        } else {
+            throw new UnsupportedOperationException( "Can't set a property after configuration becomes immutable" );
+        }
+    }
+
+    public boolean isIndexLeftBetaMemory() {
+        return this.indexLeftBetaMemory;
+    }
+
+    public void setIndexLeftBetaMemory(final boolean indexLeftBetaMemory) {
+        checkCanChange(); // throws an exception if a change isn't possible;
+        this.indexLeftBetaMemory = indexLeftBetaMemory;
+    }
+
+    public boolean isIndexRightBetaMemory() {
+        return this.indexRightBetaMemory;
+    }
+
+    public void setIndexRightBetaMemory(final boolean indexRightBetaMemory) {
+        checkCanChange(); // throws an exception if a change isn't possible;
+        this.indexRightBetaMemory = indexRightBetaMemory;
+    }
+
+    public LogicalOverride getLogicalOverride() {
+        return this.logicalOverride;
+    }
+
+    public void setLogicalOverride(final LogicalOverride logicalOverride) {
+        checkCanChange(); // throws an exception if a change isn't possible;
+        this.logicalOverride = logicalOverride;
+    }
+
+    public String getExecutorService() {
+        return executorService;
+    }
+
+    public void setExecutorService(String executorService) {
+        checkCanChange(); // throws an exception if a change isn't possible;    	
+        this.executorService = executorService;
+    }
+
+    public ConsequenceExceptionHandler getConsequenceExceptionHandler() {
+        return consequenceExceptionHandler;
+    }
+
+    public void setConsequenceExceptionHandler(ConsequenceExceptionHandler consequenceExceptionHandler) {
+        checkCanChange(); // throws an exception if a change isn't possible;        
+        this.consequenceExceptionHandler = consequenceExceptionHandler;
+    }
+
+    public String getRuleBaseUpdateHandler() {
+        return ruleBaseUpdateHandler;
+    }
+
+    public void setRuleBaseUpdateHandler(String ruleBaseUpdateHandler) {
+        checkCanChange(); // throws an exception if a change isn't possible;        
+        this.ruleBaseUpdateHandler = ruleBaseUpdateHandler;
+    }
+
+    /**
+     * Returns the actual class that is set to be used as the session clock
+     * for sessions of this rulebase
+     *  
+     * @return
+     */
+    public Class< ? extends SessionClock> getSessionClockClass() {
+        return sessionClockClass;
+    }
+
+    /**
+     * Sets the class whose instance is to be used as the session clock 
+     * for sessions of this rulebase
+     * 
+     * @param sessionClockClass
+     */
+    public void setSessionClockClass(Class< ? extends SessionClock> sessionClockClass) {
+        checkCanChange(); // throws an exception if a change isn't possible;        
+        this.sessionClockClass = sessionClockClass;
+    }
+
+    /**
+     * Sets the class name whose instance is to be used as the session clock
+     * for sessions of this rulebase
+     * 
+     * @param className
+     */
+    public void setSessionClockClass(String className) {
+        Class< ? extends SessionClock> sessionClock;
+        try {
+            ClassLoader cl = this.getClassLoader();
+            if ( cl == null ) {
+                cl = Thread.currentThread().getContextClassLoader();
+                if ( cl == null ) {
+                    cl = this.getClass().getClassLoader();
+                }
+            }
+            sessionClock = (Class< ? extends SessionClock>) cl.loadClass( className );
+        } catch ( Exception ex ) {
+            throw new RuntimeDroolsException( "Not possible to load the session clock class: " + className,
+                                              ex );
+        }
+        setSessionClockClass( sessionClock );
+    }
+
+    public AgendaGroupFactory getAgendaGroupFactory() {
+        if ( isSequential() ) {
+            if ( this.sequentialAgenda == SequentialAgenda.SEQUENTIAL ) {
+                return ArrayAgendaGroupFactory.getInstance();
+            } else {
+                return PriorityQueueAgendaGroupFactory.getInstance();
+            }
+        } else {
+            return PriorityQueueAgendaGroupFactory.getInstance();
+        }
+    }
+
+    public SequentialAgenda getSequentialAgenda() {
+        return this.sequentialAgenda;
+    }
+
+    public void setSequentialAgenda(final SequentialAgenda sequentialAgenda) {
+        checkCanChange(); // throws an exception if a change isn't possible;
+        this.sequentialAgenda = sequentialAgenda;
+    }
+
+    public NodeInstanceFactoryRegistry getProcessNodeInstanceFactoryRegistry() {
+        if ( this.processNodeInstanceFactoryRegistry == null ) {
+            initProcessNodeInstanceFactoryRegistry();
+        }
+        return this.processNodeInstanceFactoryRegistry;
+
+    }
+
+    private void initProcessNodeInstanceFactoryRegistry() {
+        this.processNodeInstanceFactoryRegistry = new NodeInstanceFactoryRegistry();
+
+        // split on each space
+        String locations[] = this.chainedProperties.getProperty( "processNodeInstanceFactoryRegistry",
+                                                                 "" ).split( "\\s" );
+
+        int i = 0;
+        // load each SemanticModule
+        for ( String factoryLocation : locations ) {
+            // trim leading/trailing spaces and quotes
+            factoryLocation = factoryLocation.trim();
+            if ( factoryLocation.startsWith( "\"" ) ) {
+                factoryLocation = factoryLocation.substring( 1 );
+            }
+            if ( factoryLocation.endsWith( "\"" ) ) {
+                factoryLocation = factoryLocation.substring( 0,
+                                                             factoryLocation.length() - 1 );
+            }
+            if ( !factoryLocation.equals( "" ) ) {
+                loadProcessNodeInstanceFactoryRegistry( factoryLocation );
+            }
+        }
+    }
+
+    private void loadProcessNodeInstanceFactoryRegistry(String factoryLocation) {
+        String content = ConfFileUtils.URLContentsToString( ConfFileUtils.getURL( factoryLocation,
+                                                                                  null,
+                                                                                  RuleBaseConfiguration.class ) );
+        
+        Map<Class< ? extends Node>, NodeInstanceFactory> map = (Map<Class< ? extends Node>, NodeInstanceFactory>) MVEL.eval( content,
+                                                                                                                                           new HashMap() );
+
+        if ( map != null ) {
+            for ( Entry<Class< ? extends Node>, NodeInstanceFactory> entry : map.entrySet() ) {
+                this.processNodeInstanceFactoryRegistry.register( entry.getKey(),
+                                                                  entry.getValue() );
+            }
+        }
+    }
+
+    private boolean determineShadowProxy(String userValue) {
+        if ( this.isSequential() ) {
+            // sequential never needs shadowing, so always override
+            return false;
+        }
+
+        if ( userValue != null ) {
+            return Boolean.valueOf( userValue ).booleanValue();
+        } else {
+            return true;
+        }
+    }
+
+    private static ConflictResolver determineConflictResolver(String className) {
+        Class clazz = null;
+        try {
+            clazz = Thread.currentThread().getContextClassLoader().loadClass( className );
+        } catch ( ClassNotFoundException e ) {
+        }
+
+        if ( clazz == null ) {
+            try {
+                clazz = RuleBaseConfiguration.class.getClassLoader().loadClass( className );
+            } catch ( ClassNotFoundException e ) {
+            }
+        }
+
+        if ( clazz != null ) {
+            try {
+                return (ConflictResolver) clazz.getMethod( "getInstance",
+                                                           null ).invoke( null,
+                                                                          null );
+            } catch ( Exception e ) {
+                throw new IllegalArgumentException( "Unable to Conflict Resolver '" + className + "'" );
+            }
+        } else {
+            throw new IllegalArgumentException( "conflict Resolver '" + className + "' not found" );
+        }
+    }
+
+    public void setConflictResolver(ConflictResolver conflictResolver) {
+        checkCanChange(); // throws an exception if a change isn't possible;
+        this.conflictResolver = conflictResolver;
+    }
+
+    public ConflictResolver getConflictResolver() {
+        return this.conflictResolver;
+    }
+
+    public void setShadowProxy(boolean shadowProxy) {
+        checkCanChange(); // throws an exception if a change isn't possible;
+        this.shadowProxy = shadowProxy;
+    }
+
+    public boolean isShadowProxy() {
+        return this.shadowProxy;
+    }
+
+    public ClassLoader getClassLoader() {
+        return classLoader;
+    }
+
+    public void setClassLoader(ClassLoader classLoader) {
+        this.classLoader = classLoader;
+    }
+
+    public void setShadowProxyExcludes(String excludes) {
+        checkCanChange(); // throws an exception if a change isn't possible;
+        if ( excludes == null || "".equals( excludes.trim() ) ) {
+            return;
+        }
+
+        if ( this.shadowProxyExcludes == null ) {
+            this.shadowProxyExcludes = new HashMap();
+        }
+
+        String[] items = excludes.split( " " );
+        for ( int i = 0; i < items.length; i++ ) {
+            String qualifiedNamespace = items[i].substring( 0,
+                                                            items[i].lastIndexOf( '.' ) ).trim();
+            String name = items[i].substring( items[i].lastIndexOf( '.' ) + 1 ).trim();
+            Object object = this.shadowProxyExcludes.get( qualifiedNamespace );
+            if ( object == null ) {
+                if ( STAR.equals( name ) ) {
+                    this.shadowProxyExcludes.put( qualifiedNamespace,
+                                                  STAR );
+                } else {
+                    // create a new list and add it
+                    List list = new ArrayList();
+                    list.add( name );
+                    this.shadowProxyExcludes.put( qualifiedNamespace,
+                                                  list );
+                }
+            } else if ( name.equals( STAR ) ) {
+                // if its a STAR now add it anyway, we don't care if it was a STAR or a List before
+                this.shadowProxyExcludes.put( qualifiedNamespace,
+                                              STAR );
+            } else {
+                // its a list so add it if it doesn't already exist
+                List list = (List) object;
+                if ( !list.contains( object ) ) {
+                    list.add( name );
+                }
+            }
+        }
+    }
+
+    public boolean isShadowed(String className) {
+        if ( this.shadowProxyExcludes == null ) {
+            return true;
+        }
+
+        String qualifiedNamespace = className.substring( 0,
+                                                         className.lastIndexOf( '.' ) ).trim();
+        String name = className.substring( className.lastIndexOf( '.' ) + 1 ).trim();
+        Object object = this.shadowProxyExcludes.get( qualifiedNamespace );
+        if ( object == null ) {
+            return true;
+        } else if ( STAR.equals( object ) ) {
+            return false;
+        } else {
+            List list = (List) object;
+            return !list.contains( name );
+        }
+    }
+
+    private static ConsequenceExceptionHandler determineConsequenceExceptionHandler(String className) {
+        return (ConsequenceExceptionHandler) instantiateClass( "ConsequenceExceptionHandler",
+                                                               className );
+    }
+
+    private static Object instantiateClass(String type,
+                                           String className) {
+        Class clazz = null;
+        try {
+            clazz = Thread.currentThread().getContextClassLoader().loadClass( className );
+        } catch ( ClassNotFoundException e ) {
+        }
+
+        if ( clazz == null ) {
+            try {
+                clazz = RuleBaseConfiguration.class.getClassLoader().loadClass( className );
+            } catch ( ClassNotFoundException e ) {
+            }
+        }
+
+        if ( clazz != null ) {
+            try {
+                return clazz.newInstance();
+            } catch ( Exception e ) {
+                throw new IllegalArgumentException( "Unable to instantiate " + type + " '" + className + "'" );
+            }
+        } else {
+            throw new IllegalArgumentException( type + " '" + className + "' not found" );
+        }
+    }
+
+    public static class AssertBehaviour
+        implements
+        Serializable {
+        private static final long           serialVersionUID = 400L;
+
+        public static final AssertBehaviour IDENTITY         = new AssertBehaviour( 0 );
+        public static final AssertBehaviour EQUALITY         = new AssertBehaviour( 1 );
+
+        private int                         value;
+
+        private AssertBehaviour(final int value) {
+            this.value = value;
+        }
+
+        public static AssertBehaviour determineAssertBehaviour(final String value) {
+            if ( "IDENTITY".equalsIgnoreCase( value ) ) {
+                return IDENTITY;
+            } else if ( "EQUALITY".equalsIgnoreCase( value ) ) {
+                return EQUALITY;
+            } else {
+                throw new IllegalArgumentException( "Illegal enum value '" + value + "' for AssertBehaviour" );
+            }
+        }
+
+        private Object readResolve() throws java.io.ObjectStreamException {
+            switch ( this.value ) {
+                case 0 :
+                    return IDENTITY;
+                case 1 :
+                    return EQUALITY;
+                default :
+                    throw new IllegalArgumentException( "Illegal enum value '" + this.value + "' for AssertBehaviour" );
+            }
+        }
+
+        public String toString() {
+            return "AssertBehaviour : " + ((this.value == 0) ? "identity" : "equality");
+        }
+    }
+
+    public static class LogicalOverride
+        implements
+        Serializable {
+        private static final long           serialVersionUID = 400L;
+
+        public static final LogicalOverride PRESERVE         = new LogicalOverride( 0 );
+        public static final LogicalOverride DISCARD          = new LogicalOverride( 1 );
+
+        private int                         value;
+
+        private LogicalOverride(final int value) {
+            this.value = value;
+        }
+
+        public static LogicalOverride determineLogicalOverride(final String value) {
+            if ( "PRESERVE".equalsIgnoreCase( value ) ) {
+                return PRESERVE;
+            } else if ( "DISCARD".equalsIgnoreCase( value ) ) {
+                return DISCARD;
+            } else {
+                throw new IllegalArgumentException( "Illegal enum value '" + value + "' for LogicalOverride" );
+            }
+        }
+
+        private Object readResolve() throws java.io.ObjectStreamException {
+            switch ( this.value ) {
+                case 0 :
+                    return PRESERVE;
+                case 1 :
+                    return DISCARD;
+                default :
+                    throw new IllegalArgumentException( "Illegal enum value '" + this.value + "' for LogicalOverride" );
+            }
+        }
+
+        public String toString() {
+            return "LogicalOverride : " + ((this.value == 0) ? "preserve" : "discard");
+        }
+    }
+
+    public static class SequentialAgenda
+        implements
+        Serializable {
+        private static final long            serialVersionUID = 400L;
+
+        public static final SequentialAgenda SEQUENTIAL       = new SequentialAgenda( 0 );
+        public static final SequentialAgenda DYNAMIC          = new SequentialAgenda( 1 );
+
+        private int                          value;
+
+        private SequentialAgenda(final int value) {
+            this.value = value;
+        }
+
+        public static SequentialAgenda determineSequentialAgenda(final String value) {
+            if ( "sequential".equalsIgnoreCase( value ) ) {
+                return SEQUENTIAL;
+            } else if ( "dynamic".equalsIgnoreCase( value ) ) {
+                return DYNAMIC;
+            } else {
+                throw new IllegalArgumentException( "Illegal enum value '" + value + "' for SequentialAgenda" );
+            }
+        }
+
+        private Object readResolve() throws java.io.ObjectStreamException {
+            switch ( this.value ) {
+                case 0 :
+                    return SEQUENTIAL;
+                case 1 :
+                    return DYNAMIC;
+                default :
+                    throw new IllegalArgumentException( "Illegal enum value '" + this.value + "' for SequentialAgenda" );
+            }
+        }
+
+        public String toString() {
+            return "SequentialAgenda : " + ((this.value == 0) ? "sequential" : "dynamic");
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuleBaseEventManager.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuleBaseEventManager.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuleBaseEventManager.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,54 @@
+package org.drools;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.drools.event.RuleBaseEventListener;
+
+/**
+ * The RuleBaseEventManager class is implemented by classes wishing to add,remove and get the various RuleBase EventListeners.
+ *
+ */
+public interface RuleBaseEventManager
+    extends
+    Serializable {
+    /**
+     * Add an event listener.
+     * 
+     * @param listener
+     *            The listener to add.
+     */
+    public void addEventListener(RuleBaseEventListener listener);
+
+    /**
+     * Remove an event listener.
+     * 
+     * @param listener
+     *            The listener to remove.
+     */
+    public void removeEventListener(RuleBaseEventListener listener);
+
+    /**
+     * Returns all event listeners.
+     * 
+     * @return listeners The listeners.
+     */
+    public List<RuleBaseEventListener> getRuleBaseEventListeners();
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuleBaseFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuleBaseFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuleBaseFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,65 @@
+package org.drools;
+
+import org.drools.util.UUIDGenerator;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * This is a utility to create rule bases based on the type of engine you wish to use.
+ * 
+ */
+public class RuleBaseFactory {
+
+    private static final RuleBaseFactory INSTANCE = new RuleBaseFactory();
+
+    private RuleBaseFactory() {
+    }
+
+    public static RuleBaseFactory getInstance() {
+        return RuleBaseFactory.INSTANCE;
+    }
+
+    /** Create a new default rule base (RETEOO type engine) */
+    public static RuleBase newRuleBase() {
+        return RuleBaseFactory.newRuleBase( RuleBase.RETEOO,
+                                            null );
+    }
+    
+    public static RuleBase newRuleBase(final RuleBaseConfiguration config) {
+        return RuleBaseFactory.newRuleBase( RuleBase.RETEOO,
+                                            config );
+    }    
+
+    public static RuleBase newRuleBase(final int type) {
+        return RuleBaseFactory.newRuleBase( type,
+                                            null );
+    }
+
+    /** Create a new RuleBase of the appropriate type */
+    public static RuleBase newRuleBase(final int type,
+                                       final RuleBaseConfiguration config) {
+        switch ( type ) {
+            case RuleBase.RETEOO :
+                return new org.drools.reteoo.ReteooRuleBase( UUIDGenerator.getInstance().generateRandomBasedUUID().toString(),
+                                                             config );
+            default :
+                throw new IllegalArgumentException( "Unknown engine type: " + type );
+
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuleIntegrationException.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuleIntegrationException.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuleIntegrationException.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,77 @@
+package org.drools;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.rule.Rule;
+
+/**
+ * Indicates an error integrating a <code>Rule</code> or <code>Package</code>
+ * into a <code>RuleBase</code>.
+ * 
+ * @see RuleBase#addRule
+ * @see RuleBase#addPackage
+ * 
+ * @author <a href="mailto:bob at eng.werken.com">bob mcwhirter </a>
+ * 
+ * @version $Id: RuleIntegrationException.java,v 1.6 2004/09/17 00:14:06
+ *          mproctor Exp $
+ */
+public class RuleIntegrationException extends IntegrationException {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+    /** The rule. */
+    private final Rule        rule;
+
+    /**
+     * @see java.lang.Exception#Exception()
+     * 
+     * @param rule
+     *            The offending rule.
+     */
+    public RuleIntegrationException(final Rule rule) {
+        super( createMessage( rule ) );
+        this.rule = rule;
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(Throwable cause)
+     * 
+     * @param rule
+     *            The offending rule.
+     */
+    public RuleIntegrationException(final Rule rule,
+                                    final Throwable cause) {
+        super( createMessage( rule ),
+               cause );
+        this.rule = rule;
+    }
+
+    /**
+     * Retrieve the <code>Rule</code>.
+     * 
+     * @return The rule.
+     */
+    public Rule getRule() {
+        return this.rule;
+    }
+
+    private static String createMessage(final Rule rule) {
+        return rule.getName() + " cannot be integrated";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuntimeDroolsException.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuntimeDroolsException.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/RuntimeDroolsException.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,66 @@
+package org.drools;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * The base Drools exception for all internal thrown exceptions. If any exceptions are thrown during the
+ * runtime execution of Drools they are considered non-recoverable and thus thrown as  Runtime exceptions
+ * all the way up to the <Code>WorkingMemory</code> at which point they are nested inside the 
+ * <code>CheckedDroolsException</code> for the user to decide how to respond.
+ * 
+ * @see RuntimeException
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ */
+public class RuntimeDroolsException extends RuntimeException {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    /**
+     * @see java.lang.Exception#Exception()
+     */
+    public RuntimeDroolsException() {
+        super();
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(String message)
+     */
+    public RuntimeDroolsException(final String message) {
+        super( message );
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(String message, Throwable cause)
+     */
+    public RuntimeDroolsException(final String message,
+                                  final Throwable cause) {
+        super( message,
+               cause );
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(Throwable cause)
+     */
+    public RuntimeDroolsException(final Throwable cause) {
+        super( cause );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/StatefulSession.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/StatefulSession.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/StatefulSession.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,75 @@
+package org.drools;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.drools.concurrent.Future;
+import org.drools.spi.AgendaFilter;
+
+/**
+ * A stateful session represents a working memory which keeps state
+ * between invocations (accumulating facts/knowledge).
+ *
+ * Caution should be used when using the async methods (take note of the javadocs for specific methods).
+ */
+public interface StatefulSession
+    extends
+    WorkingMemory {
+
+    /**
+     * Forces the workingMemory to be derefenced from
+     *
+     */
+    void dispose();
+
+    /**
+     * Insert/Assert an object asynchronously.
+     * (return immediately, even while the insertion is taking effect).
+     * The returned Future object can be queried to check on the status of the task.
+     * You should only use the async methods if you are sure you require a background
+     * insertion task to take effect (a new thread may be created).
+     * If you are not sure, then you probably don't need to use it !
+     */
+    Future asyncInsert(Object object);
+
+    Future asyncRetract(FactHandle factHandle);
+
+    Future asyncUpdate(FactHandle factHandle,
+                       Object object);
+
+    /**
+     * Insert/Assert an array of objects..
+     * (return immediately, even while the insertion is taking effect).
+     * The returned Future object can be queried to check on the status of the task.
+     * You should only use the async methods if you are sure you require a background
+     * insertion task to take effect (a new thread may be created).
+     * If you are not sure, then you probably don't need to use it !
+     */
+    Future asyncInsert(Object[] array);
+
+    /**
+     * Insert/Assert a collect of objects..
+     * (return immediately, even while the insertion is taking effect).
+     * The returned Future object can be queried to check on the status of the task.
+     * You should only use the async methods if you are sure you require a background
+     * insertion task to take effect (a new thread may be created).
+     * If you are not sure, then you probably don't need to use it !
+     */
+    Future asyncInsert(Collection collect);
+
+    /**
+     * This will initiate the firing phase (in the background).
+     * And return immediately. The returned Future object can be queried
+     * to check on the status of the task.
+     */
+    Future asyncFireAllRules();
+
+    /**
+     * This will initiate the firing phase (in the background).
+     * And return immediately. The returned Future object can be queried
+     * to check on the status of the task.
+     */
+    Future asyncFireAllRules(AgendaFilter agendaFilter);
+
+    List getRuleBaseUpdateListeners();
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/StatelessSession.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/StatelessSession.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/StatelessSession.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,109 @@
+package org.drools;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.drools.event.AgendaEventListener;
+import org.drools.event.RuleFlowEventListener;
+import org.drools.event.WorkingMemoryEventListener;
+import org.drools.spi.AgendaFilter;
+import org.drools.spi.GlobalExporter;
+import org.drools.spi.GlobalResolver;
+
+/**
+ * This represents a working memory session where state is not kept between
+ * invocations.
+ * This is typically used for "decision services" where the rules are
+ * provided all the data in one hit, and a conclusion reached by the engine.
+ * (there is no accumulation of facts/knowledge - each invocation is on a fresh session).
+ * 
+ * Each created StatelessSession can be call execute() any number of times, in a stateless manner
+ * however the GlobalResolver, unless set each time, is shared between each execute() method call.
+ * 
+ * Care should be used when using the async versions of the methods, consult the javadoc for 
+ * the specific information.
+ */
+public interface StatelessSession extends WorkingMemoryEventManager {
+        
+    void setAgendaFilter(AgendaFilter agendaFilter);
+    
+    /**
+     * Delegate used to resolve any global names not found in the global map.
+     * @param globalResolver
+     */
+    void setGlobalResolver(GlobalResolver globalResolver);
+    
+    /**
+     * Sets a global value
+     * @param identifer
+     * @param value
+     */
+    void setGlobal(String identifer, Object value);   
+    
+    /**
+     * Used to specify a global exporting strategy
+     * so that global variables can be available to StatelessSessionResults.
+     * 
+     * If this is not set, then StatelessSessionResult will have no globals.
+     * @param globalExporter
+     *                     The GlobalExporter instance
+     */
+    public void setGlobalExporter(GlobalExporter globalExporter);    
+    
+    
+    /**
+     * Insert a single fact, an fire the rules, returning when finished.
+     */
+    void execute(Object object);
+
+    /**
+     * Insert an array of facts, an fire the rules, returning when finished.
+     * This will assert the list of facts as SEPARATE facts to the engine
+     * (NOT an array).
+     */    
+    void execute(Object[] array);
+
+    /**
+     * Insert a List of facts, an fire the rules, returning when finished.
+     * This will assert the list of facts as SEPARATE facts to the engine
+     * (NOT as a List).
+     */        
+    void execute(Collection collection);    
+    
+    /**
+     * This will assert the object in the background. This is
+     * "send and forget" execution.
+     */
+    void asyncExecute(Object object);
+
+    /**
+     * This will assert the object array (as SEPARATE facts) in the background. This is
+     * "send and forget" execution.
+     */
+    void asyncExecute(Object[] array);
+
+    /**
+     * This will assert the object List (as SEPARATE facts) in the background. This is
+     * "send and forget" execution.
+     */    
+    void asyncExecute(Collection collection);      
+    
+    
+    /**
+     * Similar to the normal execute method, but this will return
+     * "results". 
+     */
+    StatelessSessionResult executeWithResults(Object object);
+
+    /**
+     * Similar to the normal execute method, but this will return
+     * "results". 
+     */    
+    StatelessSessionResult executeWithResults(Object[] array);
+
+    /**
+     * Similar to the normal execute method, but this will return
+     * "results". 
+     */   
+    StatelessSessionResult executeWithResults(Collection collection);
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/StatelessSessionResult.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/StatelessSessionResult.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/StatelessSessionResult.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,74 @@
+package org.drools;
+
+import java.util.Iterator;
+
+import org.drools.spi.GlobalResolver;
+
+/**
+ * StatelessSessionResults allow inspection of session after it has executed. Querries can still be executed, unless you serialise at which point the 
+ * WorkingMemory and RuleBase it references to execute thosa querries are lost due to being transient.
+ * 
+ * Globals must be explicitely imported into the StatelessSessionResult to be accessible, otherwise getGlobal and getGlobalResolver return null.
+ * @author mproctor
+ *
+ */
+public interface StatelessSessionResult {        
+    
+    /**
+     * Iterator all Objects inserted into the StatelessSession.
+     * @return
+     *       java.util.Iterators.
+     */
+    Iterator iterateObjects();    
+    
+    /**
+     * Iterate only those objects that match the provided ObjectFilter.
+     * @param filter
+     *             The ObjectFilter instance.
+     * @return
+     *             java.util.Iterators.
+     */
+    Iterator iterateObjects(ObjectFilter filter);   
+    
+    /**
+     * Retrieve the QueryResults of the specified query.
+     *
+     * @param query
+     *            The name of the query.
+     *
+     * @return The QueryResults of the specified query.
+     *         If no results match the query it is empty..
+     *         
+     * @throws IllegalArgumentException.
+     *         if no query named "query" is found in the rulebase.     
+     */
+    public QueryResults getQueryResults(String query);
+    
+    /**
+     * Allows for parameters to be passed to a query.
+     * @param query
+     *            The name of the query.
+     * @param arguments
+     *            The Object[] of arguments to pass to the query's parameters.
+     * @return
+     *            java.util.Iterator.
+     */
+    public QueryResults getQueryResults(final String query, final Object[] arguments);
+    
+    /**
+     * Retrieves the global value for the given identifier, note that globals must be exported from the StatelessSession to be accessible.
+     * @param identifier
+     *                 The global identifier.
+     * @return
+     *                 The instance the global identifier points to.
+     */
+    public Object getGlobal(String identifier);
+    
+    /**
+     * The GlobalResolver returned from the GlobalExporter by the StatelessSessoin
+     * @return
+     *        The GlobalResolver used for this StatelessSessionResult
+     */
+    public GlobalResolver getGlobalResolver(); 
+       
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/TemporalSession.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/TemporalSession.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/TemporalSession.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Nov 28, 2007
+ */
+package org.drools;
+
+import org.drools.temporal.SessionClock;
+
+/**
+ * A StatefulTemporalSession is a stateful session with
+ * additional functionalities for temporal reasoning. 
+ * 
+ * @author etirelli
+ *
+ */
+public interface TemporalSession<T extends SessionClock> extends StatefulSession {
+    
+    /**
+     * Returns the session clock instance for this session.
+     * 
+     * The actual session clock implementation is defined by the
+     * RuleBaseConfiguration.setSessionClockImpl() call or by
+     * setting the corresponding system property.
+     */
+    public T getSessionClock();
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/Visitor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/Visitor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/Visitor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,21 @@
+package org.drools;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public interface Visitor {
+    void visit(Object o);
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/WorkingMemory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/WorkingMemory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/WorkingMemory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,380 @@
+package org.drools;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.drools.process.instance.ProcessInstance;
+import org.drools.process.instance.WorkItemManager;
+import org.drools.spi.AgendaFilter;
+import org.drools.spi.AgendaGroup;
+import org.drools.spi.AsyncExceptionHandler;
+import org.drools.spi.GlobalResolver;
+
+/**
+ * A knowledge session for a <code>RuleBase</code>.
+ * 
+ * While this object can be serialised out, it cannot be serialised in. This is because
+ * the RuleBase reference is transient. Please see the RuleBase interface for serializing
+ * in WorkingMemories from an InputStream.
+ * 
+ */
+public interface WorkingMemory extends WorkingMemoryEventManager {
+
+    /**
+     * Returns the Agenda for this WorkingMemory. While the WorkingMemory interface is considered public, the Agenda interface 
+     * is more subject to change.
+     * @return
+     *         the Agenda
+     */
+    public Agenda getAgenda();
+
+    /**
+     * Set a specific instance as a global in this working memory. Null values will return doing nothing.
+     * The global identifier and its type must be declared in the drl.
+     * 
+     * @param identifier
+     *            the identifier under which to populate the data
+     * @param value
+     *            the global value, cannot be null
+     */
+    void setGlobal(String identifier,
+                   Object value);
+
+    /**
+     * Retrieve a specific instance of global data by identifier
+     * 
+     * @return application data or null if nothing is set under this identifier
+     */
+    Object getGlobal(String identifier);
+
+    
+    /**
+     * Sets the GlobalResolver instance to be used when resolving globals, replaces the current GlobalResolver.
+     * Typcicaly a delegating GlobalResolver is created that first gets a reference to the current GlobalResolver,
+     * for delegating
+     * 
+     * @param globalResolver
+     */
+    void setGlobalResolver(GlobalResolver globalResolver);
+    
+    /**
+     * Returns the current GlobalResolver
+     * 
+     * @return
+     */
+    GlobalResolver getGlobalResolver();
+
+    /**
+     * Retrieve the <code>RuleBase</code> for this working memory.
+     * 
+     * @return The <code>RuleBase</code>.
+     */
+    RuleBase getRuleBase();
+
+    /**
+     * Fire all items on the agenda until empty.
+     * 
+     * @throws FactException
+     *             If a RuntimeException error occurs.
+     */
+    void fireAllRules() throws FactException;
+
+    /**
+     * Fire all items on the agenda until empty, using the given AgendaFiler
+     * 
+     * @throws FactException
+     *             If a RuntimeException error occurs.
+     */
+    void fireAllRules(AgendaFilter agendaFilter) throws FactException;
+      
+    /**
+     * Fire all items on the agenda until empty or at most 'fireLimit' rules have fired
+     * 
+     * @throws FactException
+     *             If a RuntimeException error occurs.
+     */
+    void fireAllRules( int fireLimit ) throws FactException;
+
+    /**
+     * Fire all items on the agenda using the given AgendaFiler
+     * until empty or at most 'fireLimit' rules have fired
+     * 
+     * @throws FactException
+     *             If a RuntimeException error occurs.
+     */
+    void fireAllRules(final AgendaFilter agendaFilter, int fireLimit ) throws FactException;
+
+    /**
+     * Retrieve the object associated with a <code>FactHandle</code>.
+     * 
+     * 
+     * @param handle
+     *            The fact handle.
+     * 
+     * @return The associated object.
+     */
+    Object getObject(FactHandle handle);
+
+    /**
+     * Retrieve the <code>FactHandle</code> associated with an Object.
+     * 
+     * @param object
+     *            The object.
+     * 
+     * @return The associated fact handle.
+     */
+    FactHandle getFactHandle(Object object);
+
+    FactHandle getFactHandleByIdentity(final Object object);
+        
+    /**
+     * Returns an Iterator for the Objects in the Working Memory. This Iterator is not thread safe. 
+     * This means that any working memory actions during iteration may invalidate the iterator.
+     * @return
+     *     the Iterator
+     */
+    Iterator iterateObjects();
+    
+    /**
+     *  Returns an Iterator for the Objects in the Working Memory. This Iterator will filter out
+     *  any objects that the ObjectFilter does not accept. This Iterator is not thread safe.
+     * This means that any working memory actions during iteration may invalidate the iterator.
+     *  
+     * @param filter
+     * 
+     * @return
+     *     the Iterator
+     */    
+    Iterator iterateObjects(ObjectFilter filter);
+
+    /**
+     * Returns an Iterator for the FactHandles in the Working Memory. This Iterator is not thread safe.
+     * This means that any working memory actions during iteration may invalidate the iterator.
+     * @return
+     *     the Iterator
+     */    
+    Iterator iterateFactHandles();
+    
+    /**
+     *  Returns an Iterator for the Objects in the Working Memory. This Iterator will filter out
+     *  any objects that the ObjectFilter does not accept. This Iterator is not thread safe.
+     * This means that any working memory actions during iteration may invalidate the iterator.
+     *  
+     * @param filter
+     * 
+     * @return
+     *     the Iterator
+     */        
+    Iterator iterateFactHandles(ObjectFilter filter);    
+    
+    /**
+     * Returns the AgendaGroup which has the current WorkingMemory focus. The AgendaGroup interface is subject to change.
+     * @return
+     *     the AgendaGroup
+     */
+    public AgendaGroup getFocus();
+
+    /**
+     * Set the focus to the specified AgendaGroup
+     * @param focus
+     */
+    void setFocus(String focus);
+
+    /**
+     * Set the focus to the specified AgendaGroup
+     * @param focus
+     */    
+    void setFocus(AgendaGroup focus);
+        
+
+    /**
+     * Assert a fact.
+     * 
+     * @param object
+     *            The fact object.
+     * 
+     * @return The new fact-handle associated with the object.
+     * 
+     * @throws FactException
+     *             If a RuntimeException error occurs.
+     */
+    FactHandle insert(Object object) throws FactException;
+    
+    /**
+     * Retrieve the QueryResults of the specified query.
+     *
+     * @param query
+     *            The name of the query.
+     *
+     * @return The QueryResults of the specified query.
+     *         If no results match the query it is empty.
+     *         
+     * @throws IllegalArgumentException 
+     *         if no query named "query" is found in the rulebase         
+     */
+    public QueryResults getQueryResults(String query);
+    
+    /**
+     * Retrieve the QueryResults of the specified query and arguments
+     *
+     * @param query
+     *            The name of the query.
+     *            
+     * @param arguments
+     *            The arguments used for the query
+     *
+     * @return The QueryResults of the specified query.
+     *         If no results match the query it is empty.
+     *         
+     * @throws IllegalArgumentException 
+     *         if no query named "query" is found in the rulebase         
+     */    
+    public QueryResults getQueryResults(String query, Object[] arguments);
+
+    /**
+     * Insert a fact registering JavaBean <code>PropertyChangeListeners</code>
+     * on the Object to automatically trigger <code>update</code> calls
+     * if <code>dynamic</code> is <code>true</code>.
+     * 
+     * @param object
+     *            The fact object.
+     * @param dynamic
+     *            true if Drools should add JavaBean
+     *            <code>PropertyChangeListeners</code> to the object.
+     * 
+     * @return The new fact-handle associated with the object.
+     * 
+     * @throws FactException
+     *             If a RuntimeException error occurs.
+     */
+    FactHandle insert(Object object,
+                            boolean dynamic) throws FactException;
+    
+    /**
+     * Retract a fact.
+     * 
+     * @param handle
+     *            The fact-handle associated with the fact to retract.
+     * 
+     * @throws FactException
+     *             If a RuntimeException error occurs.
+     */
+    void retract(FactHandle handle) throws FactException;
+
+    /**
+     * Inform the WorkingMemory that a Fact has been modified and that it
+     * should now update the network.
+     * 
+     * @param handle
+     *            The fact-handle associated with the fact to modify.
+     * @param object
+     *            The new value of the fact.
+     * 
+     * @throws FactException
+     *             If a RuntimeException error occurs.
+     */
+    void update(FactHandle handle,
+                      Object object) throws FactException;
+    
+    /**
+     * 
+     * @param factHandle
+     */
+    public void modifyRetract(final FactHandle factHandle);
+    
+    /**
+     * 
+     * @param factHandle
+     * @param object
+     */
+    public void modifyInsert(final FactHandle factHandle,
+                             final Object object);    
+
+    /**
+     * Sets the AsyncExceptionHandler to handle exceptions thrown by the Agenda
+     * Scheduler used for duration rules.
+     * 
+     * @param handler
+     */
+    void setAsyncExceptionHandler(AsyncExceptionHandler handler);
+
+    /**
+     * Clear the Agenda. Iterates over each AgendaGroup cancalling all Activations.
+     */
+    void clearAgenda();
+
+    /**
+     * Clear the Agenda Group, cancelling all its Activations.
+     */
+    public void clearAgendaGroup(String group);
+
+    /**
+     * Clears the Activation Group, cancellings all its Activations
+     * @param group
+     */
+    public void clearActivationGroup(String group);
+    
+    /**
+     * Clears the RuleFlow group, cancelling all its Activations
+     * @param group
+     */
+    public void clearRuleFlowGroup(String group);
+    
+    /**
+     * Starts a new process instance for the process with the given id. 
+     */
+    ProcessInstance startProcess(String processId);
+
+    /**
+     * Starts a new process instance for the process with the given id. 
+     */
+    ProcessInstance startProcess(String processId, Map<String, Object> parameters);
+
+    /**
+     * Returns the list of process instances of this working memory.
+     * This list is unmodifiable.
+     * @return the list of process instances
+     */
+    public Collection getProcessInstances();
+    
+    /**
+     * Returns the process instance with the given id.
+     * @return the process instance with the given id
+     */
+    public ProcessInstance getProcessInstance(long id);
+    
+    public WorkItemManager getWorkItemManager();
+    
+    /**
+     * Stops rule firing after the currect rule finishes executing
+     *
+     */
+    public void halt();
+    
+    /**
+     * Returns the interface instance for a given entry point, so
+     * that the application can manage entry-point-scoped facts.
+     *  
+     * @param id the id of the entry point, as defined in the rules file
+     * @return
+     */
+    public EntryPointInterface getEntryPoint( String id );
+    
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/WorkingMemoryEventManager.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/WorkingMemoryEventManager.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/WorkingMemoryEventManager.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,102 @@
+package org.drools;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.drools.event.AgendaEventListener;
+import org.drools.event.RuleFlowEventListener;
+import org.drools.event.WorkingMemoryEventListener;
+
+/**
+ * The EventManager class is implemented by classes wishing to add,remove and get the various Drools EventListeners.
+ *
+ */
+public interface WorkingMemoryEventManager
+    extends
+    RuleBaseEventManager,
+    Serializable {
+    /**
+     * Add an event listener.
+     * 
+     * @param listener
+     *            The listener to add.
+     */
+    public void addEventListener(WorkingMemoryEventListener listener);
+
+    /**
+     * Remove an event listener.
+     * 
+     * @param listener
+     *            The listener to remove.
+     */
+    public void removeEventListener(WorkingMemoryEventListener listener);
+
+    /**
+     * Returns all event listeners.
+     * 
+     * @return listeners The listeners.
+     */
+    public List getWorkingMemoryEventListeners();
+
+    /**
+     * Add an event listener.
+     * 
+     * @param listener
+     *            The listener to add.
+     */
+    public void addEventListener(AgendaEventListener listener);
+
+    /**
+     * Remove an event listener.
+     * 
+     * @param listener
+     *            The listener to remove.
+     */
+    public void removeEventListener(AgendaEventListener listener);
+
+    /**
+     * Returns all event listeners.
+     * 
+     * @return listeners The listeners.
+     */
+    public List getAgendaEventListeners();
+
+    /**
+     * Add an event listener.
+     * 
+     * @param listener
+     *            The listener to add.
+     */
+    public void addEventListener(RuleFlowEventListener listener);
+
+    /**
+     * Remove an event listener.
+     * 
+     * @param listener
+     *            The listener to remove.
+     */
+    public void removeEventListener(RuleFlowEventListener listener);
+
+    /**
+     * Returns all event listeners.
+     * 
+     * @return listeners The listeners.
+     */
+    public List getRuleFlowEventListeners();
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/AgentEventListener.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/AgentEventListener.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/AgentEventListener.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,36 @@
+package org.drools.agent;
+
+/**
+ * This interface is used to provide callback style logging for the agents
+ * async events.
+ * 
+ * @author Michael Neale
+ */
+public interface AgentEventListener {
+
+    /**
+     * This sets the name for logging.
+     */
+    public void setAgentName(String name);
+    
+    /**
+     * For general info messages.
+     */
+    public void info(String message);
+    
+    /**
+     * For a warning (useful when tracking down problems).
+     */
+    public void warning(String message);
+    
+    /**
+     * An exception occurred.
+     */
+    public void exception(Exception e);
+    
+    
+    /**
+     * These should not be logged, just shown if needed.
+     */
+    public void debug(String message);
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/DirectoryScanner.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/DirectoryScanner.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/DirectoryScanner.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,57 @@
+package org.drools.agent;
+
+import java.io.File;
+import java.util.Properties;
+
+import org.drools.RuleBase;
+import org.drools.rule.Package;
+
+/**
+ * This will scan a directory for files to watch for a change.
+ * It will update the list of files only if they number of files in a directory changes.
+ * 
+ * @author Michael Neale
+ */
+public class DirectoryScanner extends PackageProvider {
+
+    private File[]      currentList;
+    private FileScanner scanner;
+    private File        dir;
+
+    void configure(Properties config) {
+        String d = config.getProperty( RuleAgent.DIRECTORY );
+
+        //now check to see whats in them dir...
+        dir = new File( d );
+        if ( !(dir.isDirectory() && dir.exists()) ) {
+            throw new IllegalArgumentException( "The directory " + d + "is not valid." );
+        }
+
+        this.currentList = dir.listFiles();
+        scanner = new FileScanner();
+        scanner.setFiles( currentList );
+
+    }
+
+    Package[] loadPackageChanges()  {
+        if ( currentList.length != dir.listFiles().length ) {
+            listener.info( "Extra files detected in the directory " + dir.getPath() );
+            currentList = dir.listFiles();
+            scanner = new FileScanner();
+            scanner.setFiles( currentList );
+        }
+        return scanner.loadPackageChanges();
+    }
+    
+    public String toString() {
+        String s = "DirectoryScanner";
+        if (dir != null) {
+            s = s + " scanning dir: " + dir.getPath();
+        }
+        if (currentList != null) {
+            s = s + " found " + currentList.length + " file(s).";            
+        }
+        return s;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/FileLoader.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/FileLoader.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/FileLoader.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,19 @@
+package org.drools.agent;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+
+
+/**
+ * This interface is mostly provided so a DRL provider can live in
+ * drools-compiler, without it, we would have circular references.
+ * @author Michael Neale
+ *
+ */
+public interface FileLoader {
+
+	public org.drools.rule.Package loadPackage(File drl) throws FileNotFoundException, IOException;
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/FileScanner.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/FileScanner.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/FileScanner.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,159 @@
+package org.drools.agent;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.drools.common.DroolsObjectInputStream;
+import org.drools.rule.Package;
+
+/**
+ * This will monitor a file to a binary package.
+ * @author Michael Neale
+ *
+ */
+public class FileScanner extends PackageProvider {
+
+    File[] files;
+    Map    lastUpdated = new HashMap();
+
+
+    /**
+     * This sets the list of files to be monitored.
+     * This takes a list of paths and files (not directories).
+     */
+    void configure(Properties config) {
+        List paths = RuleAgent.list( config.getProperty( RuleAgent.FILES ) );
+        files = new File[paths.size()];
+        for ( int i = 0; i < paths.size(); i++ ) {
+            File file = new File( (String) paths.get( i ) );
+            if ( !file.exists() ) {
+                throw new IllegalArgumentException( "The file " + file.getName() + " does not exist." );
+            }
+            files[i] = file;
+        }
+    }
+
+    /**
+     * An alternative way to configure.
+     */
+    void setFiles(File[] files) {
+        this.files = files;
+    }
+
+    /**
+     * Perform the scan.
+     * If there was an error reading the packages, this will not fail, it will
+     * just do nothing (as there may be a temporary IO issue).
+     */
+    Package[] loadPackageChanges() {
+        Package[] changes = getChangeSet();
+        return changes;
+    }
+
+
+
+
+    /**
+     * Calculate a change set, based on last updated times.
+     * (keep a map of files).
+     * @throws ClassNotFoundException
+     * @throws IOException
+     * @throws FileNotFoundException
+     */
+    private Package[] getChangeSet() {
+        if ( this.files == null ) return new Package[0];
+        List list = new ArrayList();
+        for ( int i = 0; i < files.length; i++ ) {
+            File f = files[i];
+            if ( hasChanged( f.getPath(),
+                             this.lastUpdated,
+                             f.lastModified() ) ) {
+                Package p = readPackage( f );
+                if ( p != null ) list.add( p );
+            }
+        }
+        return (Package[]) list.toArray( new Package[list.size()] );
+    }
+
+    /**
+     * If an exception occurs, it is noted, but ignored.
+     * Especially IO, as generally they are temporary.
+     */
+    private Package readPackage(File pkgFile) {
+
+    	String name = pkgFile.getName();
+    	if (!(name.endsWith(".pkg") || name.endsWith(".drl"))) {
+    		return null;
+    	}
+    	//use reflection to load if its DRL, the provider lives in drools compiler.
+    	if (pkgFile.getName().endsWith(".drl")) {
+    		try {
+				FileLoader fl = (FileLoader) Class.forName("org.drools.compiler.SourcePackageProvider").newInstance();
+				return fl.loadPackage(pkgFile);
+			} catch (Exception e) {
+				this.listener.exception(e);
+				return null;
+			}
+
+    	} else {
+
+	        Package p1_ = null;
+	        ObjectInputStream in;
+	        try {
+	            in = new DroolsObjectInputStream( new FileInputStream( pkgFile ) );
+	            p1_ = (Package) in.readObject();
+	            in.close();
+
+	        } catch ( FileNotFoundException e ) {
+	            this.listener.exception( e );
+	            this.listener.warning( "Was unable to find the file " + pkgFile.getPath() );
+	        } catch ( IOException e ) {
+	            this.listener.exception( e );
+	        } catch ( ClassNotFoundException e ) {
+	            this.listener.exception( e );
+	            this.listener.warning( "Was unable to load a class when loading a package. Perhaps it is missing from this application." );
+	        }
+	        return p1_;
+    	}
+    }
+
+    boolean hasChanged(String path,
+                       Map updates,
+                       long fileLastModified) {
+
+        if ( !updates.containsKey( path ) ) {
+            updates.put( path,
+                         new Long( fileLastModified ) );
+            return true;
+        } else {
+            Long last = (Long) updates.get( path );
+            if ( last.longValue() < fileLastModified ) {
+                updates.put( path,
+                             new Long( fileLastModified ) );
+                return true;
+            } else {
+                return false;
+            }
+        }
+
+    }
+
+    public String toString() {
+        StringBuffer buf = new StringBuffer();
+        buf.append( "FileScanner scanning: " );
+        for ( int i = 0; i < files.length; i++ ) {
+            File f = files[i];
+            buf.append( f.getPath() + " " );
+        }
+        return buf.toString();
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/HttpClientImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/HttpClientImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/HttpClientImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,76 @@
+package org.drools.agent;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+
+import org.drools.common.DroolsObjectInputStream;
+import org.drools.rule.Package;
+
+public class HttpClientImpl implements IHttpClient {
+
+    
+    
+    
+
+
+
+
+    
+    
+    
+    public LastUpdatedPing checkLastUpdated(URL url) throws IOException {
+        URLConnection con = url.openConnection();
+        HttpURLConnection httpCon = (HttpURLConnection) con;
+        try {
+            httpCon.setRequestMethod( "HEAD" );
+            
+            String lm = httpCon.getHeaderField( "lastModified" );
+            LastUpdatedPing ping = new LastUpdatedPing();
+            
+            ping.responseMessage = httpCon.getHeaderFields().toString();
+            
+            if (lm != null) {
+                ping.lastUpdated = Long.parseLong( lm );
+            }
+            
+            return ping;
+        } finally {        
+            httpCon.disconnect();
+        }
+        
+    }
+
+    public Package fetchPackage(URL url) throws IOException, ClassNotFoundException {
+        URLConnection con = url.openConnection();
+        HttpURLConnection httpCon = (HttpURLConnection) con;
+        try {
+            httpCon.setRequestMethod( "GET" );
+            InputStream in = httpCon.getInputStream();
+            
+            DroolsObjectInputStream oin = new DroolsObjectInputStream(in);
+                return (Package) oin.readObject();
+  
+        } finally {
+            httpCon.disconnect();
+        }
+    }
+    
+    public static void main(String[] args) throws Exception {
+        HttpClientImpl cl = new HttpClientImpl();
+        URL url = new URL("http://localhost:8888/org.drools.brms.JBRMS/package/com.billasurf.manufacturing.plant/SNAP");
+        
+        
+        LastUpdatedPing ping = cl.checkLastUpdated( url );
+        
+        
+        Package p = cl.fetchPackage( url );
+        
+        
+        System.err.println(ping);
+        System.err.println( ping.isError() );
+    }
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/IHttpClient.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/IHttpClient.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/IHttpClient.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,45 @@
+package org.drools.agent;
+
+import java.io.IOException;
+import java.net.URL;
+
+import org.drools.rule.Package;
+
+/**
+ * A nicely mockable Http client interface.
+ * 
+ * IM IN YR HTTP MOCKIN UR CLEINT
+ * 
+ * @author Michael Neale
+ *
+ */
+public interface IHttpClient {
+
+    public LastUpdatedPing checkLastUpdated(URL url) throws IOException;
+    
+    public Package fetchPackage(URL url) throws IOException, ClassNotFoundException;
+    
+    
+}
+
+/**
+ * This is returned when pinging for changes.
+ * 
+ * @author Michael Neale
+ */
+class LastUpdatedPing {
+    public long lastUpdated = -1;
+    public String responseMessage;
+    
+    public boolean isError() {
+        if (lastUpdated == -1) return true;
+        if (responseMessage == null) return true;
+        if (responseMessage.indexOf( "200 OK" ) == -1) return true;
+        return false;
+    }
+    
+    public String toString() {
+        return "Last updated: " + lastUpdated + "\n" + "Reponse header: " + responseMessage;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/PackageProvider.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/PackageProvider.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/PackageProvider.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,81 @@
+package org.drools.agent;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Properties;
+
+import org.drools.RuleBase;
+import org.drools.RuntimeDroolsException;
+import org.drools.rule.Package;
+
+/**
+ * All sources of packages must implement this. 
+ * @author Michael Neale
+ *
+ */
+public abstract class PackageProvider {
+
+    protected AgentEventListener listener;
+
+    /**
+     * Perform the scan, adding in any packages changed.
+     * if there are no changes, null should be returned.
+     * If there was an error reading the packages, this will not fail, it will 
+     * just do nothing (as there may be a temporary IO issue). 
+     */
+    abstract Package[] loadPackageChanges();
+
+    /**
+     * This will be passed the entire config.
+     */
+    abstract void configure(Properties config);
+
+    /**
+     * Remove the package from the rulebase if it exists in it.
+     * If it does not, does nothing.
+     */
+    static void removePackage(String name,
+                               RuleBase rb) {
+        Package[] ps = rb.getPackages();
+        if ( ps == null ) return;
+        for ( int i = 0; i < ps.length; i++ ) {
+            Package p = ps[i];
+            if ( p.getName().equals( name ) ) {
+                rb.removePackage( name );
+                return;
+            }
+        }
+    }    
+    
+    
+    static void applyChanges(RuleBase rb, boolean removeExistingPackages, Package[] ps, AgentEventListener listener) {
+        applyChanges( rb, removeExistingPackages, Arrays.asList( ps ), listener );
+    }
+    
+    static void applyChanges(RuleBase rb, boolean removeExistingPackages, Collection changes, AgentEventListener listener) {
+        rb.lock();
+        if ( changes == null ) return;
+        for ( Iterator iter = changes.iterator(); iter.hasNext(); ) {
+            Package p = (Package) iter.next();
+            
+            if ( removeExistingPackages ) {
+                removePackage( p.getName(),
+                               rb );
+            }
+            try {
+                listener.info( "Adding package called " + p.getName() );
+                rb.addPackage( p );
+            } catch ( Exception e ) {
+                throw new RuntimeDroolsException( e );
+            }
+        }
+        rb.unlock();
+    }
+    
+    public void setAgentListener(AgentEventListener listener) {
+        this.listener = listener;
+    }
+    
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/RuleAgent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/RuleAgent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/RuleAgent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,498 @@
+package org.drools.agent;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.StringTokenizer;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.drools.RuleBase;
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuleBaseFactory;
+import org.drools.RuntimeDroolsException;
+import org.drools.rule.Package;
+
+/**
+ * This manages a single rulebase, based on the properties given.
+ * You should only have ONE instance of this agent per rulebase configuration.
+ * You can get the rulebase from this agent repeatedly, as needed, or if you keep the rulebase,
+ * under most configurations it will be automatically updated.
+ *
+ * How this behaves depends on the properties that you pass into it (documented below)
+ *
+ * CONFIG OPTIONS (to be passed in as properties):
+ *  <code>newInstance</code>: setting this to "true" means that each time the rules are changed
+ *   a new instance of the rulebase is created (as opposed to updated in place)
+ *   the default is to update in place. DEFAULT: false. If you set this to true,
+ *   then you will need to call getRuleBase() each time you want to use it. If it is false,
+ *   then it means you can keep your reference to the rulebase and it will be updated automatically
+ *   (as well as any stateful sessions).
+ *
+ *  <code>poll</code>The number of seconds to poll for changes. Polling
+ *  happens in a background thread. eg: poll=30 #30 second polling.
+ *
+ *  <code>file</code>: a space seperated listing of files that make up the
+ *  packages of the rulebase. Each package can only be in one file. You can't have
+ *  packages spread across files. eg: file=/your/dir/file1.pkg file=/your/dir/file2.pkg
+ *  If the file has a .pkg extension, then it will be loaded as a binary Package (eg from the BRMS). If its a
+ *  DRL file (ie a file with a .drl extension with rule source in it), then it will attempt to compile it (of course, you will need the drools-compiler and its dependencies
+ *  available on your classpath).
+ *
+ *  <code>dir</code>: a single file system directory to monitor for packages.
+ *  As with files, each package must be in its own file.
+ *  eg: dir=/your/dir
+ *
+ *  <code>url</code>: A space seperated URL to a binary rulebase in the BRMS.
+ *  eg: url=http://server/drools-jbrms/packages/somePakage/VERSION_1
+ *  For URL you will also want a local cache directory setup:
+ *  eg: localCacheDir=/some/dir/that/exists
+ *  This is needed so that the runtime can startup and load packages even if the BRMS
+ *  is not available (or the network).
+ *
+ *  <code>name</code>
+ *  the Name is used in any logging, so each agent can be differentiated (you may have one agent per rulebase
+ *  that you need in your application).
+ *
+ *  There is also an AgentEventListener interface which you can provide which will call back when lifecycle
+ *  events happen, or errors/warnings occur. As the updating happens in a background thread, this may be important.
+ *  The default event listener logs to the System.err output stream.
+ *
+ * @author Michael Neale
+ */
+public class RuleAgent {
+
+    /**
+     * Following are property keys to be used in the property
+     * config file.
+     */
+    public static final String NEW_INSTANCE      = "newInstance";
+    public static final String FILES             = "file";
+    public static final String DIRECTORY         = "dir";
+    public static final String URLS              = "url";
+    public static final String POLL_INTERVAL     = "poll";
+    public static final String CONFIG_NAME       = "name"; //name is optional
+
+    //this is needed for cold starting when BRMS is down (ie only for URL).
+    public static final String LOCAL_URL_CACHE = "localCacheDir";
+
+    /**
+     * Here is where we have a map of providers to the key that appears on the configuration.
+     */
+    public static Map          PACKAGE_PROVIDERS = new HashMap() {
+                                                     {
+                                                         put( FILES,
+                                                              FileScanner.class );
+                                                         put( DIRECTORY,
+                                                              DirectoryScanner.class );
+                                                         put ( URLS,
+                                                               URLScanner.class );
+                                                     }
+                                                 };
+
+    /**
+     * This is true if the rulebase is created anew each time.
+     */
+    private boolean                    newInstance;
+
+    /**
+     * The rule base that is being managed.
+     */
+    private RuleBase           ruleBase;
+
+    /**
+     * the configuration for the RuleBase
+     */
+    private RuleBaseConfiguration ruleBaseConf;
+
+    /**
+     * The timer that is used to monitor for changes and deal with them.
+     */
+    private Timer              timer;
+
+    /**
+     * The providers that actually do the work.
+     */
+    List                       providers;
+
+    /**
+     * This keeps the packages around that have been loaded.
+     */
+    Map                        packages = new HashMap();
+
+    /**
+     * For logging events (important for stuff that happens in the background).
+     */
+    AgentEventListener          listener = getDefaultListener();
+
+    /**
+     * Polling interval value, in seconds, used in the Timer.
+     */
+    private int secondsToRefresh;
+
+
+
+    /**
+     * Properties configured to load up packages into a rulebase (and monitor them
+     * for changes).
+     */
+    public static RuleAgent newRuleAgent(Properties config) {
+        return newRuleAgent(config, null, null);
+    }
+
+    /**
+     * Properties configured to load up packages into a rulebase with the provided
+     * configuration (and monitor them for changes).
+     */
+    public static RuleAgent newRuleAgent(Properties config, RuleBaseConfiguration ruleBaseConf) {
+        return newRuleAgent(config, null, ruleBaseConf);
+    }
+
+    /**
+     * This allows an optional listener to be passed in.
+     * The default one prints some stuff out to System.err only when really needed.
+     */
+    public static RuleAgent newRuleAgent(Properties config, AgentEventListener listener) {
+        return newRuleAgent(config, listener, null);
+    }
+
+    /**
+     * This allows an optional listener to be passed in.
+     * The default one prints some stuff out to System.err only when really needed.
+     */
+    public static RuleAgent newRuleAgent(Properties config, AgentEventListener listener, RuleBaseConfiguration ruleBaseConf) {
+        RuleAgent agent = new RuleAgent(ruleBaseConf);
+        if ( listener != null ) {
+            agent.listener = listener;
+        }
+        agent.init(config);
+        return agent;
+    }
+
+
+
+    void init(Properties config) {
+
+        boolean newInstance = Boolean.valueOf( config.getProperty( NEW_INSTANCE,
+                                                                   "false" ) ).booleanValue();
+        int secondsToRefresh = Integer.parseInt( config.getProperty( POLL_INTERVAL,
+                                                                     "-1" ) );
+        final String name = config.getProperty( CONFIG_NAME, "default" );
+
+        listener.setAgentName( name );
+
+        listener.info( "Configuring with newInstance=" + newInstance + ", secondsToRefresh="
+                       + secondsToRefresh);
+
+        List provs = new ArrayList();
+
+        for ( Iterator iter = config.keySet().iterator(); iter.hasNext(); ) {
+            String key = (String) iter.next();
+            PackageProvider prov = getProvider( key,
+                                                config );
+            if ( prov != null ) {
+                listener.info( "Configuring package provider : " + prov.toString() );
+                provs.add( prov );
+            }
+        }
+
+
+        configure( newInstance,  provs,
+                   secondsToRefresh );
+    }
+
+    /**
+     * Pass in the name and full path to a config file that is on the classpath.
+     */
+    public static RuleAgent newRuleAgent(String propsFileName) {
+        return newRuleAgent( loadFromProperties( propsFileName ) );
+    }
+
+    /**
+     * Pass in the name and full path to a config file that is on the classpath.
+     */
+    public static RuleAgent newRuleAgent(String propsFileName, RuleBaseConfiguration ruleBaseConfiguration) {
+        return newRuleAgent( loadFromProperties( propsFileName ), ruleBaseConfiguration );
+    }
+
+    /**
+     * This takes in an optional listener. Listener must not be null in this case.
+     */
+    public static RuleAgent newRuleAgent(String propsFileName, AgentEventListener listener) {
+        return newRuleAgent( loadFromProperties( propsFileName ), listener );
+    }
+
+    /**
+     * This takes in an optional listener and RuleBaseConfiguration. Listener must not be null in this case.
+     */
+    public static RuleAgent newRuleAgent(String propsFileName, AgentEventListener listener, RuleBaseConfiguration ruleBaseConfiguration) {
+        return newRuleAgent( loadFromProperties( propsFileName ), listener, ruleBaseConfiguration );
+    }
+
+    static Properties loadFromProperties(String propsFileName) {
+        InputStream in = RuleAgent.class.getResourceAsStream( propsFileName );
+        Properties props = new Properties();
+        try {
+            props.load( in );
+            return props;
+
+        } catch ( IOException e ) {
+            throw new RuntimeDroolsException( "Unable to load properties. Needs to be the path and name of a config file on your classpath.",
+                                              e );
+        }
+    }
+
+    /**
+     * Return a configured provider ready to go.
+     */
+    private PackageProvider getProvider(String key,
+                                        Properties config) {
+        if ( !PACKAGE_PROVIDERS.containsKey( key ) ) {
+            return null;
+        }
+        Class clz = (Class) PACKAGE_PROVIDERS.get( key );
+        try {
+            PackageProvider prov = (PackageProvider) clz.newInstance( );
+            prov.setAgentListener( listener );
+            prov.configure( config );
+            return prov;
+        } catch ( InstantiationException e ) {
+            throw new RuntimeDroolsException( "Unable to load up a package provider for " + key,
+                                              e );
+        } catch ( IllegalAccessException e ) {
+            throw new RuntimeDroolsException( "Unable to load up a package provider for " + key,
+                                              e );
+        }
+    }
+
+    synchronized void configure(boolean newInstance,
+                                List provs,
+                                int secondsToRefresh) {
+        this.newInstance = newInstance;
+        this.providers = provs;
+
+
+        //run it the first time for each.
+        refreshRuleBase();
+
+        if ( secondsToRefresh != -1 ) {
+            startPolling( secondsToRefresh );
+        }
+
+    }
+
+    public void refreshRuleBase() {
+
+        List changedPackages = new ArrayList();
+
+        for ( Iterator iter = providers.iterator(); iter.hasNext(); ) {
+            PackageProvider prov = (PackageProvider) iter.next();
+            Package[] changes = checkForChanges( prov );
+            if (changes != null && changes.length > 0) {
+                changedPackages.addAll( Arrays.asList( changes ) );
+            }
+        }
+
+        if (changedPackages.size() > 0) {
+            listener.info( "Applying changes to the rulebase." );
+            //we have a change
+            if (this.newInstance) {
+                listener.info( "Creating a new rulebase as per settings." );
+                //blow away old
+                this.ruleBase = RuleBaseFactory.newRuleBase( this.ruleBaseConf );
+
+                //need to store ALL packages
+                for ( Iterator iter = changedPackages.iterator(); iter.hasNext(); ) {
+                    Package element = (Package) iter.next();
+                    this.packages.put( element.getName(), element ); //replace
+                }
+                //get packages from full name
+                PackageProvider.applyChanges( this.ruleBase, false, this.packages.values(), this.listener );
+            } else {
+                PackageProvider.applyChanges( this.ruleBase, true, changedPackages, this.listener );
+            }
+        }
+
+
+    }
+
+    private synchronized Package[] checkForChanges(PackageProvider prov) {
+        listener.debug( "SCANNING FOR CHANGE " + prov.toString() );
+        if (this.ruleBase == null) ruleBase = RuleBaseFactory.newRuleBase( this.ruleBaseConf );
+        Package[] changes = prov.loadPackageChanges();
+        return changes;
+    }
+
+    /**
+     * Convert a space seperated list into a List of stuff.
+     * If a filename or whatnot has a space in it, you can put double quotes around it
+     * and it will read it in as one token.
+     */
+    static List list(String property) {
+        if ( property == null ) return Collections.EMPTY_LIST;
+        char[] cs = property.toCharArray();
+        boolean inquotes = false;
+        List items = new ArrayList();
+        String current = "";
+        for ( int i = 0; i < cs.length; i++ ) {
+            char c = cs[i];
+            switch ( c ) {
+                case '\"' :
+                    if (inquotes) {
+                        items.add( current );
+                        current = "";
+                    }
+                    inquotes = !inquotes;
+                    break;
+
+
+                default :
+                    if (!inquotes &&
+                            (c == ' ' || c == '\n' || c == '\r' || c == '\t')) {
+                        if (current.trim() != "") {
+                            items.add( current );
+                            current = "";
+                        }
+                    } else {
+                        current = current + c;
+                    }
+                    break;
+            }
+        }
+        if (current.trim() != "") {
+            items.add( current );
+        }
+
+        return items;
+    }
+
+    /**
+     * Return a current rulebase.
+     * Depending on the configuration, this may be a new object each time
+     * the rules are updated.
+     *
+     */
+    public synchronized RuleBase getRuleBase() {
+        return this.ruleBase;
+    }
+
+    RuleAgent(RuleBaseConfiguration ruleBaseConf) {
+        if ( ruleBaseConf == null ) {
+            this.ruleBaseConf = new RuleBaseConfiguration();
+        } else {
+            this.ruleBaseConf = ruleBaseConf;
+        }
+    }
+
+    /**
+     * Stop the polling (if it is happening)
+     */
+    public synchronized void stopPolling() {
+        if ( this.timer != null ) timer.cancel();
+        timer = null;
+    }
+
+    /**
+     * Will start polling. If polling is already running it does nothing.
+     *
+     */
+    public synchronized void startPolling() {
+        if ( this.timer == null ) {
+            startPolling( this.secondsToRefresh );
+        }
+    }
+
+    /**
+     * Will start polling. If polling is already happening and of the same interval
+     * it will do nothing, if the interval is different it will stop the current Timer
+     * and create a new Timer for the new interval.
+     * @param secondsToRefresh
+     */
+    public synchronized void startPolling(int secondsToRefresh) {
+        if ( this.timer != null ) {
+            if ( this.secondsToRefresh != secondsToRefresh ) {
+                stopPolling();
+            } else {
+                // do nothing.
+                return;
+            }
+        }
+
+        this.secondsToRefresh = secondsToRefresh;
+        int interval = this.secondsToRefresh * 1000;
+        //now schedule it for polling
+        timer = new Timer( true );
+        timer.schedule( new TimerTask() {
+                            public void run() {
+                                try {
+
+                                    listener.debug( "Checking for updates." );
+                                    refreshRuleBase();
+
+                                } catch (Exception e) {
+                                    //don't want to stop execution here.
+                                    listener.exception( e );
+                                }
+                            }
+                        },
+                        interval,
+                        interval );
+    }
+
+    boolean isNewInstance() {
+        return newInstance;
+    }
+
+    public synchronized boolean isPolling() {
+        return this.timer != null;
+    }
+
+    /**
+     * This should only be used once, on setup.
+     * @return
+     */
+    private AgentEventListener getDefaultListener() {
+
+        return new AgentEventListener() {
+
+            private String name;
+
+            public String time() {
+                Date d = new Date();
+                return d.toString();
+            }
+
+            public void exception(Exception e) {
+                System.err.println("RuleAgent(" + name + ") EXCEPTION (" + time() + "): " + e.getMessage() + ". Stack trace should follow.");
+                e.printStackTrace( System.err );
+            }
+
+            public void info(String message) {
+                System.err.println("RuleAgent(" + name + ") INFO (" + time() + "): " + message);
+            }
+
+            public void warning(String message) {
+                System.err.println("RuleAgent(" + name + ") WARNING (" + time() + "): " + message);
+            }
+
+            public void debug(String message) {
+                //do nothing...
+            }
+
+            public void setAgentName(String name) {
+                this.name = name;
+
+            }
+
+        };
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/RuleBaseAgentCache.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/RuleBaseAgentCache.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/RuleBaseAgentCache.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,38 @@
+package org.drools.agent;
+
+import java.util.Properties;
+
+import org.drools.RuleBase;
+
+public class RuleBaseAgentCache {
+
+    private static final RuleBaseAgentCache INSTANCE = new RuleBaseAgentCache();
+
+    private RuleBaseAgentCache() {
+    }
+
+    public static RuleBaseAgentCache instance() {
+        return INSTANCE;
+    }
+
+    /**
+     * Return a rulebase by name.
+     * This name may be the name of a pre configured rulebase, 
+     * or the name of a config properties file to be found
+     * on the classpath.
+     */
+    public RuleBase getRuleBase(String name) {
+        throw new UnsupportedOperationException( "Not done yet !" );
+    }
+
+    /** 
+     * Pass in a pre populated properties file.
+     * It will then map this config to the given name for future use.
+     * @return A RuleBase ready to go. 
+     */
+    public RuleBase configureRuleBase(String name,
+                                      Properties props) {
+        return null;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/URLScanner.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/URLScanner.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/agent/URLScanner.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,178 @@
+package org.drools.agent;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.rule.Package;
+
+public class URLScanner extends PackageProvider {
+
+    //this is the URLs we are managing
+    URL[]       urls;
+
+    //this is only set if we are using a local cache - only fall back on this
+    //when URL connection is not available.
+    FileScanner localCacheFileScanner;
+
+    //this is used to access the remote resources
+    IHttpClient httpClient = new HttpClientImpl();
+
+    //a record of the last updated URL timestamps
+    Map         lastUpdated = new HashMap();
+
+    File        localCacheDir;
+
+    void configure(Properties config) {
+        List uriList = RuleAgent.list( config.getProperty( RuleAgent.URLS ) );
+        urls = new URL[uriList.size()];
+        for ( int i = 0; i < uriList.size(); i++ ) {
+            String url = (String) uriList.get( i );
+            try {
+                urls[i] = new URL( url );
+            } catch ( MalformedURLException e ) {
+                throw new RuntimeException( "The URL " + url + " is not valid.",
+                                            e );
+            }
+        }
+
+        //if we have a local cache, check its all kosher
+        String localCache = config.getProperty( RuleAgent.LOCAL_URL_CACHE );
+        if ( localCache != null ) {
+            localCacheDir = new File( localCache );
+            if ( !localCacheDir.isDirectory() ) {
+                throw new RuntimeDroolsException( "The local cache dir " + localCache + " is a file, not a directory." );
+            }
+            this.localCacheFileScanner = new FileScanner();
+            this.localCacheFileScanner.setFiles( getFiles( urls, localCacheDir ) );
+        }
+    }
+
+    File[] getFiles(URL[] urls, File cacheDir) {
+        File[] fs = new File[urls.length];
+        for ( int i = 0; i < urls.length; i++ ) {
+            URL u = urls[i];
+            File f = getLocalCacheFileForURL( cacheDir, u );
+            fs[i] = f;
+        }
+        return fs;
+    }
+
+    static File getLocalCacheFileForURL(File cacheDir, URL u) {
+        File f;
+        try {
+            f = new File( cacheDir,
+                          URLEncoder.encode(  u.toExternalForm(), "UTF-8" ) + ".pkg" );
+        } catch ( UnsupportedEncodingException e ) {
+            throw new RuntimeDroolsException( e );
+        }
+        return f;
+    }
+
+
+
+    Package[] loadPackageChanges() { //void updateRuleBase(RuleBase rb, boolean removeExistingPackages) {
+        Package[] changes = null;
+        try {
+            changes = getChangeSet();
+            return changes;
+        } catch ( IOException e ) {
+            if (this.localCacheFileScanner != null) {
+                listener.warning( "Falling back to local cache." );
+                return localCacheFileScanner.loadPackageChanges();
+            }
+            listener.exception( e );
+        } catch ( ClassNotFoundException e ) {
+            this.listener.exception( e );
+            this.listener.warning( "Was unable to load a class when loading a package. Perhaps it is missing from this application." );
+        }
+        return null;
+    }
+
+    private Package[] getChangeSet() throws IOException, ClassNotFoundException {
+        if ( this.urls == null ) return new Package[0];
+        List list = new ArrayList();
+        for ( int i = 0; i < urls.length; i++ ) {
+            URL u = urls[i];
+            if ( hasChanged( u, this.lastUpdated) ) {
+                Package p = readPackage( u );
+                if ( p == null ) return null;
+                list.add( p );
+                if (localCacheDir != null) {
+                    writeLocalCacheCopy(p, u, localCacheDir);
+                }
+            }
+        }
+        return (Package[]) list.toArray( new Package[list.size()] );
+    }
+
+    private void writeLocalCacheCopy(Package p, URL u, File localCacheDir) {
+        File local = getLocalCacheFileForURL( localCacheDir, u );
+        if (local.exists()) local.delete();
+
+        try {
+            ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(local));
+            out.writeObject( p );
+            out.flush();
+            out.close();
+        } catch (IOException e) {
+            listener.exception( e );
+            listener.warning( "Was an error with the local cache directory " + localCacheDir.getPath() );
+        }
+
+    }
+
+    private Package readPackage(URL u) throws IOException, ClassNotFoundException {
+        return httpClient.fetchPackage( u );
+    }
+
+    private boolean hasChanged(URL u, Map updates) throws IOException {
+        LastUpdatedPing pong = httpClient.checkLastUpdated( u );
+        if (pong.isError()) {
+            listener.warning( "Was an error contacting " + u.toExternalForm() + ". Reponse header: " + pong.responseMessage );
+            throw new IOException("Was unable to reach server.");
+        }
+
+        String url = u.toExternalForm();
+        if ( !updates.containsKey( url ) ) {
+            updates.put( url,
+                         new Long( pong.lastUpdated ) );
+            return true;
+        } else {
+            Long last = (Long) updates.get( url );
+            if ( last.longValue() < pong.lastUpdated ) {
+                updates.put( url,
+                             new Long( pong.lastUpdated ) );
+                return true;
+            } else {
+                return false;
+            }
+        }
+    }
+
+    public String toString() {
+        String s = "URLScanner monitoring URLs: ";
+        if (this.urls != null) {
+            for ( int i = 0; i < urls.length; i++ ) {
+                URL url = urls[i];
+                s = s + " " + url.toExternalForm();
+            }
+        }
+        if (this.localCacheDir != null) {
+            s = s + " with local cache dir of " + this.localCacheDir.getPath();
+        }
+        return s;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/AnnotationVisitor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/AnnotationVisitor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/AnnotationVisitor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,92 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm;
+
+/**
+ * A visitor to visit a Java annotation. The methods of this interface must be
+ * called in the following order: (<tt>visit<tt> | <tt>visitEnum<tt> | 
+ * <tt>visitAnnotation<tt> | <tt>visitArray<tt>)* <tt>visitEnd<tt>.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public interface AnnotationVisitor {
+
+    /**
+     * Visits a primitive value of the annotation.
+     * 
+     * @param name the value name.
+     * @param value the actual value, whose type must be {@link Byte},
+     *        {@link Boolean}, {@link Character}, {@link Short},
+     *        {@link Integer}, {@link Long}, {@link Float}, {@link Double},
+     *        {@link String} or {@link Type}.
+     */
+    void visit(String name,
+               Object value);
+
+    /**
+     * Visits an enumeration value of the annotation.
+     * 
+     * @param name the value name.
+     * @param desc the class descriptor of the enumeration class.
+     * @param value the actual enumeration value.
+     */
+    void visitEnum(String name,
+                   String desc,
+                   String value);
+
+    /**
+     * Visits a nested annotation value of the annotation.
+     * 
+     * @param name the value name.
+     * @param desc the class descriptor of the nested annotation class.
+     * @return a non null visitor to visit the actual nested annotation value.
+     *         <i>The nested annotation value must be fully visited before
+     *         calling other methods on this annotation visitor</i>.
+     */
+    AnnotationVisitor visitAnnotation(String name,
+                                      String desc);
+
+    /**
+     * Visits an array value of the annotation.
+     * 
+     * @param name the value name.
+     * @return a non null visitor to visit the actual array value elements. The
+     *         'name' parameters passed to the methods of this visitor are
+     *         ignored. <i>All the array values must be visited before calling
+     *         other methods on this annotation visitor</i>.
+     */
+    AnnotationVisitor visitArray(String name);
+
+    /**
+     * Visits the end of the annotation.
+     */
+    void visitEnd();
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/AnnotationWriter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/AnnotationWriter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/AnnotationWriter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,347 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm;
+
+/**
+ * An {@link AnnotationVisitor} that generates annotations in bytecode form.
+ * 
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+final class AnnotationWriter
+    implements
+    AnnotationVisitor {
+
+    /**
+     * The class writer to which this annotation must be added.
+     */
+    private final ClassWriter cw;
+
+    /**
+     * The number of values in this annotation.
+     */
+    private int               size;
+
+    /**
+     * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation 
+     * writers used for annotation default and annotation arrays use unnamed
+     * values.
+     */
+    private final boolean     named;
+
+    /**
+     * The annotation values in bytecode form. This byte vector only contains
+     * the values themselves, i.e. the number of values must be stored as a
+     * unsigned short just before these bytes.
+     */
+    private final ByteVector  bv;
+
+    /**
+     * The byte vector to be used to store the number of values of this
+     * annotation. See {@link #bv}.
+     */
+    private final ByteVector  parent;
+
+    /**
+     * Where the number of values of this annotation must be stored in
+     * {@link #parent}.
+     */
+    private final int         offset;
+
+    /**
+     * Next annotation writer. This field is used to store annotation lists.
+     */
+    AnnotationWriter          next;
+
+    /**
+     * Previous annotation writer. This field is used to store annotation lists.
+     */
+    AnnotationWriter          prev;
+
+    // ------------------------------------------------------------------------
+    // Constructor
+    // ------------------------------------------------------------------------
+
+    /**
+     * Constructs a new {@link AnnotationWriter}.
+     * 
+     * @param cw the class writer to which this annotation must be added.
+     * @param named <tt>true<tt> if values are named, <tt>false</tt> otherwise.
+     * @param bv where the annotation values must be stored.
+     * @param parent where the number of annotation values must be stored.
+     * @param offset where in <tt>parent</tt> the number of annotation values must 
+     *      be stored.
+     */
+    AnnotationWriter(final ClassWriter cw,
+                     final boolean named,
+                     final ByteVector bv,
+                     final ByteVector parent,
+                     final int offset) {
+        this.cw = cw;
+        this.named = named;
+        this.bv = bv;
+        this.parent = parent;
+        this.offset = offset;
+    }
+
+    // ------------------------------------------------------------------------
+    // Implementation of the AnnotationVisitor interface
+    // ------------------------------------------------------------------------
+
+    public void visit(final String name,
+                      final Object value) {
+        ++this.size;
+        if ( this.named ) {
+            this.bv.putShort( this.cw.newUTF8( name ) );
+        }
+        if ( value instanceof String ) {
+            this.bv.put12( 's',
+                           this.cw.newUTF8( (String) value ) );
+        } else if ( value instanceof Byte ) {
+            this.bv.put12( 'B',
+                           this.cw.newInteger( ((Byte) value).byteValue() ).index );
+        } else if ( value instanceof Boolean ) {
+            final int v = ((Boolean) value).booleanValue() ? 1 : 0;
+            this.bv.put12( 'Z',
+                           this.cw.newInteger( v ).index );
+        } else if ( value instanceof Character ) {
+            this.bv.put12( 'C',
+                           this.cw.newInteger( ((Character) value).charValue() ).index );
+        } else if ( value instanceof Short ) {
+            this.bv.put12( 'S',
+                           this.cw.newInteger( ((Short) value).shortValue() ).index );
+        } else if ( value instanceof Type ) {
+            this.bv.put12( 'c',
+                           this.cw.newUTF8( ((Type) value).getDescriptor() ) );
+        } else if ( value instanceof byte[] ) {
+            final byte[] v = (byte[]) value;
+            this.bv.put12( '[',
+                           v.length );
+            for ( int i = 0; i < v.length; i++ ) {
+                this.bv.put12( 'B',
+                               this.cw.newInteger( v[i] ).index );
+            }
+        } else if ( value instanceof boolean[] ) {
+            final boolean[] v = (boolean[]) value;
+            this.bv.put12( '[',
+                           v.length );
+            for ( int i = 0; i < v.length; i++ ) {
+                this.bv.put12( 'Z',
+                               this.cw.newInteger( v[i] ? 1 : 0 ).index );
+            }
+        } else if ( value instanceof short[] ) {
+            final short[] v = (short[]) value;
+            this.bv.put12( '[',
+                           v.length );
+            for ( int i = 0; i < v.length; i++ ) {
+                this.bv.put12( 'S',
+                               this.cw.newInteger( v[i] ).index );
+            }
+        } else if ( value instanceof char[] ) {
+            final char[] v = (char[]) value;
+            this.bv.put12( '[',
+                           v.length );
+            for ( int i = 0; i < v.length; i++ ) {
+                this.bv.put12( 'C',
+                               this.cw.newInteger( v[i] ).index );
+            }
+        } else if ( value instanceof int[] ) {
+            final int[] v = (int[]) value;
+            this.bv.put12( '[',
+                           v.length );
+            for ( int i = 0; i < v.length; i++ ) {
+                this.bv.put12( 'I',
+                               this.cw.newInteger( v[i] ).index );
+            }
+        } else if ( value instanceof long[] ) {
+            final long[] v = (long[]) value;
+            this.bv.put12( '[',
+                           v.length );
+            for ( int i = 0; i < v.length; i++ ) {
+                this.bv.put12( 'J',
+                               this.cw.newLong( v[i] ).index );
+            }
+        } else if ( value instanceof float[] ) {
+            final float[] v = (float[]) value;
+            this.bv.put12( '[',
+                           v.length );
+            for ( int i = 0; i < v.length; i++ ) {
+                this.bv.put12( 'F',
+                               this.cw.newFloat( v[i] ).index );
+            }
+        } else if ( value instanceof double[] ) {
+            final double[] v = (double[]) value;
+            this.bv.put12( '[',
+                           v.length );
+            for ( int i = 0; i < v.length; i++ ) {
+                this.bv.put12( 'D',
+                               this.cw.newDouble( v[i] ).index );
+            }
+        } else {
+            final Item i = this.cw.newConstItem( value );
+            this.bv.put12( ".s.IFJDCS".charAt( i.type ),
+                           i.index );
+        }
+    }
+
+    public void visitEnum(final String name,
+                          final String desc,
+                          final String value) {
+        ++this.size;
+        if ( this.named ) {
+            this.bv.putShort( this.cw.newUTF8( name ) );
+        }
+        this.bv.put12( 'e',
+                       this.cw.newUTF8( desc ) ).putShort( this.cw.newUTF8( value ) );
+    }
+
+    public AnnotationVisitor visitAnnotation(final String name,
+                                             final String desc) {
+        ++this.size;
+        if ( this.named ) {
+            this.bv.putShort( this.cw.newUTF8( name ) );
+        }
+        // write tag and type, and reserve space for values count
+        this.bv.put12( '@',
+                       this.cw.newUTF8( desc ) ).putShort( 0 );
+        return new AnnotationWriter( this.cw,
+                                     true,
+                                     this.bv,
+                                     this.bv,
+                                     this.bv.length - 2 );
+    }
+
+    public AnnotationVisitor visitArray(final String name) {
+        ++this.size;
+        if ( this.named ) {
+            this.bv.putShort( this.cw.newUTF8( name ) );
+        }
+        // write tag, and reserve space for array size
+        this.bv.put12( '[',
+                       0 );
+        return new AnnotationWriter( this.cw,
+                                     false,
+                                     this.bv,
+                                     this.bv,
+                                     this.bv.length - 2 );
+    }
+
+    public void visitEnd() {
+        if ( this.parent != null ) {
+            final byte[] data = this.parent.data;
+            data[this.offset] = (byte) (this.size >>> 8);
+            data[this.offset + 1] = (byte) this.size;
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns the size of this annotation writer list.
+     * 
+     * @return the size of this annotation writer list.
+     */
+    int getSize() {
+        int size = 0;
+        AnnotationWriter aw = this;
+        while ( aw != null ) {
+            size += aw.bv.length;
+            aw = aw.next;
+        }
+        return size;
+    }
+
+    /**
+     * Puts the annotations of this annotation writer list into the given byte
+     * vector.
+     * 
+     * @param out where the annotations must be put.
+     */
+    void put(final ByteVector out) {
+        int n = 0;
+        int size = 2;
+        AnnotationWriter aw = this;
+        AnnotationWriter last = null;
+        while ( aw != null ) {
+            ++n;
+            size += aw.bv.length;
+            aw.visitEnd(); // in case user forgot to call visitEnd
+            aw.prev = last;
+            last = aw;
+            aw = aw.next;
+        }
+        out.putInt( size );
+        out.putShort( n );
+        aw = last;
+        while ( aw != null ) {
+            out.putByteArray( aw.bv.data,
+                              0,
+                              aw.bv.length );
+            aw = aw.prev;
+        }
+    }
+
+    /**
+     * Puts the given annotation lists into the given byte vector.
+     * 
+     * @param panns an array of annotation writer lists.
+     * @param out where the annotations must be put.
+     */
+    static void put(final AnnotationWriter[] panns,
+                    final ByteVector out) {
+        int size = 1 + 2 * panns.length;
+        for ( int i = 0; i < panns.length; ++i ) {
+            size += panns[i] == null ? 0 : panns[i].getSize();
+        }
+        out.putInt( size ).putByte( panns.length );
+        for ( int i = 0; i < panns.length; ++i ) {
+            AnnotationWriter aw = panns[i];
+            AnnotationWriter last = null;
+            int n = 0;
+            while ( aw != null ) {
+                ++n;
+                aw.visitEnd(); // in case user forgot to call visitEnd
+                aw.prev = last;
+                last = aw;
+                aw = aw.next;
+            }
+            out.putShort( n );
+            aw = last;
+            while ( aw != null ) {
+                out.putByteArray( aw.bv.data,
+                                  0,
+                                  aw.bv.length );
+                aw = aw.prev;
+            }
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Attribute.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Attribute.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Attribute.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,260 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm;
+
+/**
+ * A non standard class, field, method or code attribute.
+ * 
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class Attribute {
+
+    /**
+     * The type of this attribute.
+     */
+    public final String type;
+
+    /**
+     * The raw value of this attribute, used only for unknown attributes.
+     */
+    byte[]              value;
+
+    /**
+     * The next attribute in this attribute list. May be <tt>null</tt>.
+     */
+    Attribute           next;
+
+    /**
+     * Constructs a new empty attribute.
+     * 
+     * @param type the type of the attribute.
+     */
+    protected Attribute(final String type) {
+        this.type = type;
+    }
+
+    /**
+     * Returns <tt>true</tt> if this type of attribute is unknown. The default
+     * implementation of this method always returns <tt>true</tt>.
+     * 
+     * @return <tt>true</tt> if this type of attribute is unknown.
+     */
+    public boolean isUnknown() {
+        return true;
+    }
+
+    /**
+     * Returns <tt>true</tt> if this type of attribute is a code attribute.
+     * 
+     * @return <tt>true</tt> if this type of attribute is a code attribute.
+     */
+    public boolean isCodeAttribute() {
+        return false;
+    }
+
+    /**
+     * Returns the labels corresponding to this attribute.
+     * 
+     * @return the labels corresponding to this attribute, or <tt>null</tt> if
+     *         this attribute is not a code attribute that contains labels.
+     */
+    protected Label[] getLabels() {
+        return null;
+    }
+
+    /**
+     * Reads a {@link #type type} attribute. This method must return a <i>new</i>
+     * {@link Attribute} object, of type {@link #type type}, corresponding to
+     * the <tt>len</tt> bytes starting at the given offset, in the given class
+     * reader.
+     * 
+     * @param cr the class that contains the attribute to be read.
+     * @param off index of the first byte of the attribute's content in {@link
+     *        ClassReader#b cr.b}. The 6 attribute header bytes, containing the
+     *        type and the length of the attribute, are not taken into account
+     *        here.
+     * @param len the length of the attribute's content.
+     * @param buf buffer to be used to call
+     *        {@link ClassReader#readUTF8 readUTF8},
+     *        {@link ClassReader#readClass(int,char[]) readClass} or
+     *        {@link ClassReader#readConst readConst}.
+     * @param codeOff index of the first byte of code's attribute content in
+     *        {@link ClassReader#b cr.b}, or -1 if the attribute to be read is
+     *        not a code attribute. The 6 attribute header bytes, containing the
+     *        type and the length of the attribute, are not taken into account
+     *        here.
+     * @param labels the labels of the method's code, or <tt>null</tt> if the
+     *        attribute to be read is not a code attribute.
+     * @return a <i>new</i> {@link Attribute} object corresponding to the given
+     *         bytes.
+     */
+    protected Attribute read(final ClassReader cr,
+                             final int off,
+                             final int len,
+                             final char[] buf,
+                             final int codeOff,
+                             final Label[] labels) {
+        final Attribute attr = new Attribute( this.type );
+        attr.value = new byte[len];
+        System.arraycopy( cr.b,
+                          off,
+                          attr.value,
+                          0,
+                          len );
+        return attr;
+    }
+
+    /**
+     * Returns the byte array form of this attribute.
+     * 
+     * @param cw the class to which this attribute must be added. This parameter
+     *        can be used to add to the constant pool of this class the items
+     *        that corresponds to this attribute.
+     * @param code the bytecode of the method corresponding to this code
+     *        attribute, or <tt>null</tt> if this attribute is not a code
+     *        attributes.
+     * @param len the length of the bytecode of the method corresponding to this
+     *        code attribute, or <tt>null</tt> if this attribute is not a code
+     *        attribute.
+     * @param maxStack the maximum stack size of the method corresponding to
+     *        this code attribute, or -1 if this attribute is not a code
+     *        attribute.
+     * @param maxLocals the maximum number of local variables of the method
+     *        corresponding to this code attribute, or -1 if this attribute is
+     *        not a code attribute.
+     * @return the byte array form of this attribute.
+     */
+    protected ByteVector write(final ClassWriter cw,
+                               final byte[] code,
+                               final int len,
+                               final int maxStack,
+                               final int maxLocals) {
+        final ByteVector v = new ByteVector();
+        v.data = this.value;
+        v.length = this.value.length;
+        return v;
+    }
+
+    /**
+     * Returns the length of the attribute list that begins with this attribute.
+     * 
+     * @return the length of the attribute list that begins with this attribute.
+     */
+    final int getCount() {
+        int count = 0;
+        Attribute attr = this;
+        while ( attr != null ) {
+            count += 1;
+            attr = attr.next;
+        }
+        return count;
+    }
+
+    /**
+     * Returns the size of all the attributes in this attribute list.
+     * 
+     * @param cw the class writer to be used to convert the attributes into byte
+     *        arrays, with the {@link #write write} method.
+     * @param code the bytecode of the method corresponding to these code
+     *        attributes, or <tt>null</tt> if these attributes are not code
+     *        attributes.
+     * @param len the length of the bytecode of the method corresponding to
+     *        these code attributes, or <tt>null</tt> if these attributes are
+     *        not code attributes.
+     * @param maxStack the maximum stack size of the method corresponding to
+     *        these code attributes, or -1 if these attributes are not code
+     *        attributes.
+     * @param maxLocals the maximum number of local variables of the method
+     *        corresponding to these code attributes, or -1 if these attributes
+     *        are not code attributes.
+     * @return the size of all the attributes in this attribute list. This size
+     *         includes the size of the attribute headers.
+     */
+    final int getSize(final ClassWriter cw,
+                      final byte[] code,
+                      final int len,
+                      final int maxStack,
+                      final int maxLocals) {
+        Attribute attr = this;
+        int size = 0;
+        while ( attr != null ) {
+            cw.newUTF8( attr.type );
+            size += attr.write( cw,
+                                code,
+                                len,
+                                maxStack,
+                                maxLocals ).length + 6;
+            attr = attr.next;
+        }
+        return size;
+    }
+
+    /**
+     * Writes all the attributes of this attribute list in the given byte
+     * vector.
+     * 
+     * @param cw the class writer to be used to convert the attributes into byte
+     *        arrays, with the {@link #write write} method.
+     * @param code the bytecode of the method corresponding to these code
+     *        attributes, or <tt>null</tt> if these attributes are not code
+     *        attributes.
+     * @param len the length of the bytecode of the method corresponding to
+     *        these code attributes, or <tt>null</tt> if these attributes are
+     *        not code attributes.
+     * @param maxStack the maximum stack size of the method corresponding to
+     *        these code attributes, or -1 if these attributes are not code
+     *        attributes.
+     * @param maxLocals the maximum number of local variables of the method
+     *        corresponding to these code attributes, or -1 if these attributes
+     *        are not code attributes.
+     * @param out where the attributes must be written.
+     */
+    final void put(final ClassWriter cw,
+                   final byte[] code,
+                   final int len,
+                   final int maxStack,
+                   final int maxLocals,
+                   final ByteVector out) {
+        Attribute attr = this;
+        while ( attr != null ) {
+            final ByteVector b = attr.write( cw,
+                                             code,
+                                             len,
+                                             maxStack,
+                                             maxLocals );
+            out.putShort( cw.newUTF8( attr.type ) ).putInt( b.length );
+            out.putByteArray( b.data,
+                              0,
+                              b.length );
+            attr = attr.next;
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/ByteVector.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/ByteVector.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/ByteVector.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,304 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm;
+
+/**
+ * A dynamically extensible vector of bytes. This class is roughly equivalent to
+ * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.
+ * 
+ * @author Eric Bruneton
+ */
+public class ByteVector {
+
+    /**
+     * The content of this vector.
+     */
+    byte[] data;
+
+    /**
+     * Actual number of bytes in this vector.
+     */
+    int    length;
+
+    /**
+     * Constructs a new {@link ByteVector ByteVector} with a default initial
+     * size.
+     */
+    public ByteVector() {
+        this.data = new byte[64];
+    }
+
+    /**
+     * Constructs a new {@link ByteVector ByteVector} with the given initial
+     * size.
+     * 
+     * @param initialSize the initial size of the byte vector to be constructed.
+     */
+    public ByteVector(final int initialSize) {
+        this.data = new byte[initialSize];
+    }
+
+    /**
+     * Puts a byte into this byte vector. The byte vector is automatically
+     * enlarged if necessary.
+     * 
+     * @param b a byte.
+     * @return this byte vector.
+     */
+    public ByteVector putByte(final int b) {
+        int length = this.length;
+        if ( length + 1 > this.data.length ) {
+            enlarge( 1 );
+        }
+        this.data[length++] = (byte) b;
+        this.length = length;
+        return this;
+    }
+
+    /**
+     * Puts two bytes into this byte vector. The byte vector is automatically
+     * enlarged if necessary.
+     * 
+     * @param b1 a byte.
+     * @param b2 another byte.
+     * @return this byte vector.
+     */
+    ByteVector put11(final int b1,
+                     final int b2) {
+        int length = this.length;
+        if ( length + 2 > this.data.length ) {
+            enlarge( 2 );
+        }
+        final byte[] data = this.data;
+        data[length++] = (byte) b1;
+        data[length++] = (byte) b2;
+        this.length = length;
+        return this;
+    }
+
+    /**
+     * Puts a short into this byte vector. The byte vector is automatically
+     * enlarged if necessary.
+     * 
+     * @param s a short.
+     * @return this byte vector.
+     */
+    public ByteVector putShort(final int s) {
+        int length = this.length;
+        if ( length + 2 > this.data.length ) {
+            enlarge( 2 );
+        }
+        final byte[] data = this.data;
+        data[length++] = (byte) (s >>> 8);
+        data[length++] = (byte) s;
+        this.length = length;
+        return this;
+    }
+
+    /**
+     * Puts a byte and a short into this byte vector. The byte vector is
+     * automatically enlarged if necessary.
+     * 
+     * @param b a byte.
+     * @param s a short.
+     * @return this byte vector.
+     */
+    ByteVector put12(final int b,
+                     final int s) {
+        int length = this.length;
+        if ( length + 3 > this.data.length ) {
+            enlarge( 3 );
+        }
+        final byte[] data = this.data;
+        data[length++] = (byte) b;
+        data[length++] = (byte) (s >>> 8);
+        data[length++] = (byte) s;
+        this.length = length;
+        return this;
+    }
+
+    /**
+     * Puts an int into this byte vector. The byte vector is automatically
+     * enlarged if necessary.
+     * 
+     * @param i an int.
+     * @return this byte vector.
+     */
+    public ByteVector putInt(final int i) {
+        int length = this.length;
+        if ( length + 4 > this.data.length ) {
+            enlarge( 4 );
+        }
+        final byte[] data = this.data;
+        data[length++] = (byte) (i >>> 24);
+        data[length++] = (byte) (i >>> 16);
+        data[length++] = (byte) (i >>> 8);
+        data[length++] = (byte) i;
+        this.length = length;
+        return this;
+    }
+
+    /**
+     * Puts a long into this byte vector. The byte vector is automatically
+     * enlarged if necessary.
+     * 
+     * @param l a long.
+     * @return this byte vector.
+     */
+    public ByteVector putLong(final long l) {
+        int length = this.length;
+        if ( length + 8 > this.data.length ) {
+            enlarge( 8 );
+        }
+        final byte[] data = this.data;
+        int i = (int) (l >>> 32);
+        data[length++] = (byte) (i >>> 24);
+        data[length++] = (byte) (i >>> 16);
+        data[length++] = (byte) (i >>> 8);
+        data[length++] = (byte) i;
+        i = (int) l;
+        data[length++] = (byte) (i >>> 24);
+        data[length++] = (byte) (i >>> 16);
+        data[length++] = (byte) (i >>> 8);
+        data[length++] = (byte) i;
+        this.length = length;
+        return this;
+    }
+
+    /**
+     * Puts an UTF8 string into this byte vector. The byte vector is
+     * automatically enlarged if necessary.
+     * 
+     * @param s a String.
+     * @return this byte vector.
+     */
+    public ByteVector putUTF8(final String s) {
+        final int charLength = s.length();
+        if ( this.length + 2 + charLength > this.data.length ) {
+            enlarge( 2 + charLength );
+        }
+        int len = this.length;
+        byte[] data = this.data;
+        // optimistic algorithm: instead of computing the byte length and then
+        // serializing the string (which requires two loops), we assume the byte
+        // length is equal to char length (which is the most frequent case), and
+        // we start serializing the string right away. During the serialization,
+        // if we find that this assumption is wrong, we continue with the
+        // general method.
+        data[len++] = (byte) (charLength >>> 8);
+        data[len++] = (byte) (charLength);
+        for ( int i = 0; i < charLength; ++i ) {
+            char c = s.charAt( i );
+            if ( c >= '\001' && c <= '\177' ) {
+                data[len++] = (byte) c;
+            } else {
+                int byteLength = i;
+                for ( int j = i; j < charLength; ++j ) {
+                    c = s.charAt( j );
+                    if ( c >= '\001' && c <= '\177' ) {
+                        byteLength++;
+                    } else if ( c > '\u07FF' ) {
+                        byteLength += 3;
+                    } else {
+                        byteLength += 2;
+                    }
+                }
+                data[this.length] = (byte) (byteLength >>> 8);
+                data[this.length + 1] = (byte) (byteLength);
+                if ( this.length + 2 + byteLength > data.length ) {
+                    this.length = len;
+                    enlarge( 2 + byteLength );
+                    data = this.data;
+                }
+                for ( int j = i; j < charLength; ++j ) {
+                    c = s.charAt( j );
+                    if ( c >= '\001' && c <= '\177' ) {
+                        data[len++] = (byte) c;
+                    } else if ( c > '\u07FF' ) {
+                        data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
+                        data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
+                        data[len++] = (byte) (0x80 | c & 0x3F);
+                    } else {
+                        data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
+                        data[len++] = (byte) (0x80 | c & 0x3F);
+                    }
+                }
+                break;
+            }
+        }
+        this.length = len;
+        return this;
+    }
+
+    /**
+     * Puts an array of bytes into this byte vector. The byte vector is
+     * automatically enlarged if necessary.
+     * 
+     * @param b an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
+     *        null bytes into this byte vector.
+     * @param off index of the fist byte of b that must be copied.
+     * @param len number of bytes of b that must be copied.
+     * @return this byte vector.
+     */
+    public ByteVector putByteArray(final byte[] b,
+                                   final int off,
+                                   final int len) {
+        if ( this.length + len > this.data.length ) {
+            enlarge( len );
+        }
+        if ( b != null ) {
+            System.arraycopy( b,
+                              off,
+                              this.data,
+                              this.length,
+                              len );
+        }
+        this.length += len;
+        return this;
+    }
+
+    /**
+     * Enlarge this byte vector so that it can receive n more bytes.
+     * 
+     * @param size number of additional bytes that this byte vector should be
+     *        able to receive.
+     */
+    private void enlarge(final int size) {
+        final int length1 = 2 * this.data.length;
+        final int length2 = this.length + size;
+        final byte[] newData = new byte[length1 > length2 ? length1 : length2];
+        System.arraycopy( this.data,
+                          0,
+                          newData,
+                          0,
+                          this.length );
+        this.data = newData;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/ClassAdapter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/ClassAdapter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/ClassAdapter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,132 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm;
+
+/**
+ * An empty {@link ClassVisitor} that delegates to another {@link ClassVisitor}.
+ * This class can be used as a super class to quickly implement usefull class
+ * adapter classes, just by overriding the necessary methods.
+ * 
+ * @author Eric Bruneton
+ */
+public class ClassAdapter
+    implements
+    ClassVisitor {
+
+    /**
+     * The {@link ClassVisitor} to which this adapter delegates calls.
+     */
+    protected ClassVisitor cv;
+
+    /**
+     * Constructs a new {@link ClassAdapter} object.
+     * 
+     * @param cv the class visitor to which this adapter must delegate calls.
+     */
+    public ClassAdapter(final ClassVisitor cv) {
+        this.cv = cv;
+    }
+
+    public void visit(final int version,
+                      final int access,
+                      final String name,
+                      final String signature,
+                      final String superName,
+                      final String[] interfaces) {
+        this.cv.visit( version,
+                       access,
+                       name,
+                       signature,
+                       superName,
+                       interfaces );
+    }
+
+    public void visitSource(final String source,
+                            final String debug) {
+        this.cv.visitSource( source,
+                             debug );
+    }
+
+    public void visitOuterClass(final String owner,
+                                final String name,
+                                final String desc) {
+        this.cv.visitOuterClass( owner,
+                                 name,
+                                 desc );
+    }
+
+    public AnnotationVisitor visitAnnotation(final String desc,
+                                             final boolean visible) {
+        return this.cv.visitAnnotation( desc,
+                                        visible );
+    }
+
+    public void visitAttribute(final Attribute attr) {
+        this.cv.visitAttribute( attr );
+    }
+
+    public void visitInnerClass(final String name,
+                                final String outerName,
+                                final String innerName,
+                                final int access) {
+        this.cv.visitInnerClass( name,
+                                 outerName,
+                                 innerName,
+                                 access );
+    }
+
+    public FieldVisitor visitField(final int access,
+                                   final String name,
+                                   final String desc,
+                                   final String signature,
+                                   final Object value) {
+        return this.cv.visitField( access,
+                                   name,
+                                   desc,
+                                   signature,
+                                   value );
+    }
+
+    public MethodVisitor visitMethod(final int access,
+                                     final String name,
+                                     final String desc,
+                                     final String signature,
+                                     final String[] exceptions) {
+        return this.cv.visitMethod( access,
+                                    name,
+                                    desc,
+                                    signature,
+                                    exceptions );
+    }
+
+    public void visitEnd() {
+        this.cv.visitEnd();
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/ClassReader.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/ClassReader.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/ClassReader.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,1735 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A Java class parser to make a {@link ClassVisitor} visit an existing class.
+ * This class parses a byte array conforming to the Java class file format and
+ * calls the appropriate visit methods of a given class visitor for each field,
+ * method and bytecode instruction encountered.
+ * 
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class ClassReader {
+
+    /**
+     * The class to be parsed. <i>The content of this array must not be
+     * modified. This field is intended for {@link Attribute} sub classes, and
+     * is normally not needed by class generators or adapters.</i>
+     */
+    public final byte[] b;
+
+    /**
+     * The start index of each constant pool item in {@link #b b}, plus one.
+     * The one byte offset skips the constant pool item tag that indicates its
+     * type.
+     */
+    private int[]       items;
+
+    /**
+     * The String objects corresponding to the CONSTANT_Utf8 items. This cache
+     * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
+     * which GREATLY improves performances (by a factor 2 to 3). This caching
+     * strategy could be extended to all constant pool items, but its benefit
+     * would not be so great for these items (because they are much less
+     * expensive to parse than CONSTANT_Utf8 items).
+     */
+    private String[]    strings;
+
+    /**
+     * Maximum length of the strings contained in the constant pool of the
+     * class.
+     */
+    private int         maxStringLength;
+
+    /**
+     * Start index of the class header information (access, name...) in
+     * {@link #b b}.
+     */
+    public final int    header;
+
+    // ------------------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------------------
+
+    /**
+     * Constructs a new {@link ClassReader} object.
+     * 
+     * @param b the bytecode of the class to be read.
+     */
+    public ClassReader(final byte[] b) {
+        this( b,
+              0,
+              b.length );
+    }
+
+    /**
+     * Constructs a new {@link ClassReader} object.
+     * 
+     * @param b the bytecode of the class to be read.
+     * @param off the start offset of the class data.
+     * @param len the length of the class data.
+     */
+    public ClassReader(final byte[] b,
+                       final int off,
+                       final int len) {
+        this.b = b;
+        // parses the constant pool
+        this.items = new int[readUnsignedShort( off + 8 )];
+        final int ll = this.items.length;
+        this.strings = new String[ll];
+        int max = 0;
+        int index = off + 10;
+        for ( int i = 1; i < ll; ++i ) {
+            this.items[i] = index + 1;
+            final int tag = b[index];
+            int size;
+            switch ( tag ) {
+                case ClassWriter.FIELD :
+                case ClassWriter.METH :
+                case ClassWriter.IMETH :
+                case ClassWriter.INT :
+                case ClassWriter.FLOAT :
+                case ClassWriter.NAME_TYPE :
+                    size = 5;
+                    break;
+                case ClassWriter.LONG :
+                case ClassWriter.DOUBLE :
+                    size = 9;
+                    ++i;
+                    break;
+                case ClassWriter.UTF8 :
+                    size = 3 + readUnsignedShort( index + 1 );
+                    if ( size > max ) {
+                        max = size;
+                    }
+                    break;
+                // case ClassWriter.CLASS:
+                // case ClassWriter.STR:
+                default :
+                    size = 3;
+                    break;
+            }
+            index += size;
+        }
+        this.maxStringLength = max;
+        // the class header information starts just after the constant pool
+        this.header = index;
+    }
+
+    /**
+     * Copies the constant pool data into the given {@link ClassWriter}. Should
+     * be called before the {@link #accept(ClassVisitor,boolean)} method.
+     * 
+     * @param classWriter the {@link ClassWriter} to copy constant pool into.
+     */
+    void copyPool(final ClassWriter classWriter) {
+        final char[] buf = new char[this.maxStringLength];
+        final int ll = this.items.length;
+        final Item[] items2 = new Item[ll];
+        for ( int i = 1; i < ll; i++ ) {
+            int index = this.items[i];
+            final int tag = this.b[index - 1];
+            final Item item = new Item( i );
+            int nameType;
+            switch ( tag ) {
+                case ClassWriter.FIELD :
+                case ClassWriter.METH :
+                case ClassWriter.IMETH :
+                    nameType = this.items[readUnsignedShort( index + 2 )];
+                    item.set( tag,
+                              readClass( index,
+                                         buf ),
+                              readUTF8( nameType,
+                                        buf ),
+                              readUTF8( nameType + 2,
+                                        buf ) );
+                    break;
+
+                case ClassWriter.INT :
+                    item.set( readInt( index ) );
+                    break;
+
+                case ClassWriter.FLOAT :
+                    item.set( Float.intBitsToFloat( readInt( index ) ) );
+                    break;
+
+                case ClassWriter.NAME_TYPE :
+                    item.set( tag,
+                              readUTF8( index,
+                                        buf ),
+                              readUTF8( index + 2,
+                                        buf ),
+                              null );
+                    break;
+
+                case ClassWriter.LONG :
+                    item.set( readLong( index ) );
+                    ++i;
+                    break;
+
+                case ClassWriter.DOUBLE :
+                    item.set( Double.longBitsToDouble( readLong( index ) ) );
+                    ++i;
+                    break;
+
+                case ClassWriter.UTF8 : {
+                    String s = this.strings[i];
+                    if ( s == null ) {
+                        index = this.items[i];
+                        s = this.strings[i] = readUTF( index + 2,
+                                                       readUnsignedShort( index ),
+                                                       buf );
+                    }
+                    item.set( tag,
+                              s,
+                              null,
+                              null );
+                }
+                    break;
+
+                // case ClassWriter.STR:
+                // case ClassWriter.CLASS:
+                default :
+                    item.set( tag,
+                              readUTF8( index,
+                                        buf ),
+                              null,
+                              null );
+                    break;
+            }
+
+            final int index2 = item.hashCode % items2.length;
+            item.next = items2[index2];
+            items2[index2] = item;
+        }
+
+        final int off = this.items[1] - 1;
+        classWriter.pool.putByteArray( this.b,
+                                       off,
+                                       this.header - off );
+        classWriter.items = items2;
+        classWriter.threshold = (int) (0.75d * ll);
+        classWriter.index = ll;
+    }
+
+    /**
+     * Constructs a new {@link ClassReader} object.
+     * 
+     * @param is an input stream from which to read the class.
+     * @throws IOException if a problem occurs during reading.
+     */
+    public ClassReader(final InputStream is) throws IOException {
+        this( readClass( is ) );
+    }
+
+    /**
+     * Constructs a new {@link ClassReader} object.
+     * 
+     * @param name the fully qualified name of the class to be read.
+     * @throws IOException if an exception occurs during reading.
+     */
+    public ClassReader(final String name) throws IOException {
+        this( ClassLoader.getSystemResourceAsStream( name.replace( '.',
+                                                                   '/' ) + ".class" ) );
+    }
+
+    /**
+     * Reads the bytecode of a class.
+     * 
+     * @param is an input stream from which to read the class.
+     * @return the bytecode read from the given input stream.
+     * @throws IOException if a problem occurs during reading.
+     */
+    private static byte[] readClass(final InputStream is) throws IOException {
+        if ( is == null ) {
+            throw new IOException( "Class not found" );
+        }
+        byte[] b = new byte[is.available()];
+        int len = 0;
+        while ( true ) {
+            final int n = is.read( b,
+                                   len,
+                                   b.length - len );
+            if ( n == -1 ) {
+                if ( len < b.length ) {
+                    final byte[] c = new byte[len];
+                    System.arraycopy( b,
+                                      0,
+                                      c,
+                                      0,
+                                      len );
+                    b = c;
+                }
+                return b;
+            }
+            len += n;
+            if ( len == b.length ) {
+                final byte[] c = new byte[b.length + 1000];
+                System.arraycopy( b,
+                                  0,
+                                  c,
+                                  0,
+                                  len );
+                b = c;
+            }
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Public methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Makes the given visitor visit the Java class of this {@link ClassReader}.
+     * This class is the one specified in the constructor (see
+     * {@link #ClassReader(byte[]) ClassReader}).
+     * 
+     * @param classVisitor the visitor that must visit this class.
+     * @param skipDebug <tt>true</tt> if the debug information of the class
+     *        must not be visited. In this case the
+     *        {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
+     *        {@link MethodVisitor#visitLineNumber visitLineNumber} methods will
+     *        not be called.
+     */
+    public void accept(final ClassVisitor classVisitor,
+                       final boolean skipDebug) {
+        accept( classVisitor,
+                new Attribute[0],
+                skipDebug );
+    }
+
+    /**
+     * Makes the given visitor visit the Java class of this {@link ClassReader}.
+     * This class is the one specified in the constructor (see
+     * {@link #ClassReader(byte[]) ClassReader}).
+     * 
+     * @param classVisitor the visitor that must visit this class.
+     * @param attrs prototypes of the attributes that must be parsed during the
+     *        visit of the class. Any attribute whose type is not equal to the
+     *        type of one the prototypes will be ignored.
+     * @param skipDebug <tt>true</tt> if the debug information of the class
+     *        must not be visited. In this case the
+     *        {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
+     *        {@link MethodVisitor#visitLineNumber visitLineNumber} methods will
+     *        not be called.
+     */
+    public void accept(final ClassVisitor classVisitor,
+                       final Attribute[] attrs,
+                       final boolean skipDebug) {
+        final byte[] b = this.b; // the bytecode array
+        final char[] c = new char[this.maxStringLength]; // buffer used to read strings
+        int i, j, k; // loop variables
+        int u, v, w; // indexes in b
+        Attribute attr;
+
+        int access;
+        String name;
+        String desc;
+        String attrName;
+        String signature;
+        int anns = 0;
+        int ianns = 0;
+        Attribute cattrs = null;
+
+        // visits the header
+        u = this.header;
+        access = readUnsignedShort( u );
+        name = readClass( u + 2,
+                          c );
+        v = this.items[readUnsignedShort( u + 4 )];
+        final String superClassName = v == 0 ? null : readUTF8( v,
+                                                                c );
+        final String[] implementedItfs = new String[readUnsignedShort( u + 6 )];
+        w = 0;
+        u += 8;
+        for ( i = 0; i < implementedItfs.length; ++i ) {
+            implementedItfs[i] = readClass( u,
+                                            c );
+            u += 2;
+        }
+
+        // skips fields and methods
+        v = u;
+        i = readUnsignedShort( v );
+        v += 2;
+        for ( ; i > 0; --i ) {
+            j = readUnsignedShort( v + 6 );
+            v += 8;
+            for ( ; j > 0; --j ) {
+                v += 6 + readInt( v + 2 );
+            }
+        }
+        i = readUnsignedShort( v );
+        v += 2;
+        for ( ; i > 0; --i ) {
+            j = readUnsignedShort( v + 6 );
+            v += 8;
+            for ( ; j > 0; --j ) {
+                v += 6 + readInt( v + 2 );
+            }
+        }
+        // reads the class's attributes
+        signature = null;
+        String sourceFile = null;
+        String sourceDebug = null;
+        String enclosingOwner = null;
+        String enclosingName = null;
+        String enclosingDesc = null;
+
+        i = readUnsignedShort( v );
+        v += 2;
+        for ( ; i > 0; --i ) {
+            attrName = readUTF8( v,
+                                 c );
+            if ( attrName.equals( "SourceFile" ) ) {
+                sourceFile = readUTF8( v + 6,
+                                       c );
+            } else if ( attrName.equals( "Deprecated" ) ) {
+                access |= Opcodes.ACC_DEPRECATED;
+            } else if ( attrName.equals( "Synthetic" ) ) {
+                access |= Opcodes.ACC_SYNTHETIC;
+            } else if ( attrName.equals( "Annotation" ) ) {
+                access |= Opcodes.ACC_ANNOTATION;
+            } else if ( attrName.equals( "Enum" ) ) {
+                access |= Opcodes.ACC_ENUM;
+            } else if ( attrName.equals( "InnerClasses" ) ) {
+                w = v + 6;
+            } else if ( attrName.equals( "Signature" ) ) {
+                signature = readUTF8( v + 6,
+                                      c );
+            } else if ( attrName.equals( "SourceDebugExtension" ) ) {
+                final int len = readInt( v + 2 );
+                sourceDebug = readUTF( v + 6,
+                                       len,
+                                       new char[len] );
+            } else if ( attrName.equals( "EnclosingMethod" ) ) {
+                enclosingOwner = readClass( v + 6,
+                                            c );
+                final int item = readUnsignedShort( v + 8 );
+                if ( item != 0 ) {
+                    enclosingName = readUTF8( this.items[item],
+                                              c );
+                    enclosingDesc = readUTF8( this.items[item] + 2,
+                                              c );
+                }
+            } else if ( attrName.equals( "RuntimeVisibleAnnotations" ) ) {
+                anns = v + 6;
+            } else if ( attrName.equals( "RuntimeInvisibleAnnotations" ) ) {
+                ianns = v + 6;
+            } else {
+                attr = readAttribute( attrs,
+                                      attrName,
+                                      v + 6,
+                                      readInt( v + 2 ),
+                                      c,
+                                      -1,
+                                      null );
+                if ( attr != null ) {
+                    attr.next = cattrs;
+                    cattrs = attr;
+                }
+            }
+            v += 6 + readInt( v + 2 );
+        }
+        // calls the visit method
+        classVisitor.visit( readInt( 4 ),
+                            access,
+                            name,
+                            signature,
+                            superClassName,
+                            implementedItfs );
+
+        // calls the visitSource method
+        if ( sourceFile != null || sourceDebug != null ) {
+            classVisitor.visitSource( sourceFile,
+                                      sourceDebug );
+        }
+
+        // calls the visitOuterClass method
+        if ( enclosingOwner != null ) {
+            classVisitor.visitOuterClass( enclosingOwner,
+                                          enclosingName,
+                                          enclosingDesc );
+        }
+
+        // visits the class annotations
+        for ( i = 1; i >= 0; --i ) {
+            v = i == 0 ? ianns : anns;
+            if ( v != 0 ) {
+                j = readUnsignedShort( v );
+                v += 2;
+                for ( ; j > 0; --j ) {
+                    desc = readUTF8( v,
+                                     c );
+                    v += 2;
+                    v = readAnnotationValues( v,
+                                              c,
+                                              classVisitor.visitAnnotation( desc,
+                                                                            i != 0 ) );
+                }
+            }
+        }
+
+        // visits the class attributes
+        while ( cattrs != null ) {
+            attr = cattrs.next;
+            cattrs.next = null;
+            classVisitor.visitAttribute( cattrs );
+            cattrs = attr;
+        }
+
+        // class the visitInnerClass method
+        if ( w != 0 ) {
+            i = readUnsignedShort( w );
+            w += 2;
+            for ( ; i > 0; --i ) {
+                classVisitor.visitInnerClass( readUnsignedShort( w ) == 0 ? null : readClass( w,
+                                                                                              c ),
+                                              readUnsignedShort( w + 2 ) == 0 ? null : readClass( w + 2,
+                                                                                                  c ),
+                                              readUnsignedShort( w + 4 ) == 0 ? null : readUTF8( w + 4,
+                                                                                                 c ),
+                                              readUnsignedShort( w + 6 ) );
+                w += 8;
+            }
+        }
+
+        // visits the fields
+        i = readUnsignedShort( u );
+        u += 2;
+        for ( ; i > 0; --i ) {
+            access = readUnsignedShort( u );
+            name = readUTF8( u + 2,
+                             c );
+            desc = readUTF8( u + 4,
+                             c );
+            // visits the field's attributes and looks for a ConstantValue
+            // attribute
+            int fieldValueItem = 0;
+            signature = null;
+            anns = 0;
+            ianns = 0;
+            cattrs = null;
+
+            j = readUnsignedShort( u + 6 );
+            u += 8;
+            for ( ; j > 0; --j ) {
+                attrName = readUTF8( u,
+                                     c );
+                if ( attrName.equals( "ConstantValue" ) ) {
+                    fieldValueItem = readUnsignedShort( u + 6 );
+                } else if ( attrName.equals( "Synthetic" ) ) {
+                    access |= Opcodes.ACC_SYNTHETIC;
+                } else if ( attrName.equals( "Deprecated" ) ) {
+                    access |= Opcodes.ACC_DEPRECATED;
+                } else if ( attrName.equals( "Enum" ) ) {
+                    access |= Opcodes.ACC_ENUM;
+                } else if ( attrName.equals( "Signature" ) ) {
+                    signature = readUTF8( u + 6,
+                                          c );
+                } else if ( attrName.equals( "RuntimeVisibleAnnotations" ) ) {
+                    anns = u + 6;
+                } else if ( attrName.equals( "RuntimeInvisibleAnnotations" ) ) {
+                    ianns = u + 6;
+                } else {
+                    attr = readAttribute( attrs,
+                                          attrName,
+                                          u + 6,
+                                          readInt( u + 2 ),
+                                          c,
+                                          -1,
+                                          null );
+                    if ( attr != null ) {
+                        attr.next = cattrs;
+                        cattrs = attr;
+                    }
+                }
+                u += 6 + readInt( u + 2 );
+            }
+            // reads the field's value, if any
+            final Object value = (fieldValueItem == 0 ? null : readConst( fieldValueItem,
+                                                                          c ));
+            // visits the field
+            final FieldVisitor fv = classVisitor.visitField( access,
+                                                             name,
+                                                             desc,
+                                                             signature,
+                                                             value );
+            // visits the field annotations and attributes
+            if ( fv != null ) {
+                for ( j = 1; j >= 0; --j ) {
+                    v = j == 0 ? ianns : anns;
+                    if ( v != 0 ) {
+                        k = readUnsignedShort( v );
+                        v += 2;
+                        for ( ; k > 0; --k ) {
+                            desc = readUTF8( v,
+                                             c );
+                            v += 2;
+                            v = readAnnotationValues( v,
+                                                      c,
+                                                      fv.visitAnnotation( desc,
+                                                                          j != 0 ) );
+                        }
+                    }
+                }
+                while ( cattrs != null ) {
+                    attr = cattrs.next;
+                    cattrs.next = null;
+                    fv.visitAttribute( cattrs );
+                    cattrs = attr;
+                }
+                fv.visitEnd();
+            }
+        }
+
+        // visits the methods
+        i = readUnsignedShort( u );
+        u += 2;
+        for ( ; i > 0; --i ) {
+            final int u0 = u + 6;
+            access = readUnsignedShort( u );
+            name = readUTF8( u + 2,
+                             c );
+            desc = readUTF8( u + 4,
+                             c );
+            signature = null;
+            anns = 0;
+            ianns = 0;
+            int dann = 0;
+            int mpanns = 0;
+            int impanns = 0;
+            cattrs = null;
+            v = 0;
+            w = 0;
+
+            // looks for Code and Exceptions attributes
+            j = readUnsignedShort( u + 6 );
+            u += 8;
+            for ( ; j > 0; --j ) {
+                attrName = readUTF8( u,
+                                     c );
+                u += 2;
+                final int attrSize = readInt( u );
+                u += 4;
+                if ( attrName.equals( "Code" ) ) {
+                    v = u;
+                } else if ( attrName.equals( "Exceptions" ) ) {
+                    w = u;
+                } else if ( attrName.equals( "Synthetic" ) ) {
+                    access |= Opcodes.ACC_SYNTHETIC;
+                } else if ( attrName.equals( "Varargs" ) ) {
+                    access |= Opcodes.ACC_VARARGS;
+                } else if ( attrName.equals( "Bridge" ) ) {
+                    access |= Opcodes.ACC_BRIDGE;
+                } else if ( attrName.equals( "Deprecated" ) ) {
+                    access |= Opcodes.ACC_DEPRECATED;
+                } else if ( attrName.equals( "Signature" ) ) {
+                    signature = readUTF8( u,
+                                          c );
+                } else if ( attrName.equals( "AnnotationDefault" ) ) {
+                    dann = u;
+                } else if ( attrName.equals( "RuntimeVisibleAnnotations" ) ) {
+                    anns = u;
+                } else if ( attrName.equals( "RuntimeInvisibleAnnotations" ) ) {
+                    ianns = u;
+                } else if ( attrName.equals( "RuntimeVisibleParameterAnnotations" ) ) {
+                    mpanns = u;
+                } else if ( attrName.equals( "RuntimeInvisibleParameterAnnotations" ) ) {
+                    impanns = u;
+                } else {
+                    attr = readAttribute( attrs,
+                                          attrName,
+                                          u,
+                                          attrSize,
+                                          c,
+                                          -1,
+                                          null );
+                    if ( attr != null ) {
+                        attr.next = cattrs;
+                        cattrs = attr;
+                    }
+                }
+                u += attrSize;
+            }
+            // reads declared exceptions
+            String[] exceptions;
+            if ( w == 0 ) {
+                exceptions = null;
+            } else {
+                exceptions = new String[readUnsignedShort( w )];
+                w += 2;
+                for ( j = 0; j < exceptions.length; ++j ) {
+                    exceptions[j] = readClass( w,
+                                               c );
+                    w += 2;
+                }
+            }
+
+            // visits the method's code, if any
+            final MethodVisitor mv = classVisitor.visitMethod( access,
+                                                               name,
+                                                               desc,
+                                                               signature,
+                                                               exceptions );
+
+            if ( mv != null ) {
+                /*
+                 * if the returned MethodVisitor is in fact a MethodWriter, it
+                 * means there is no method adapter between the reader and the
+                 * writer. If, in addition, the writer's constant pool was
+                 * copied from this reader (mw.cw.cr == this), and the signature
+                 * and exceptions of the method have not been changed, then it
+                 * is possible to skip all visit events and just copy the
+                 * original code of the method to the writer (the access, name
+                 * and descriptor can have been changed, this is not important
+                 * since they are not copied as is from the reader).
+                 */
+                if ( mv instanceof MethodWriter ) {
+                    final MethodWriter mw = (MethodWriter) mv;
+                    if ( mw.cw.cr == this ) {
+                        if ( signature == mw.signature ) {
+                            boolean sameExceptions = false;
+                            if ( exceptions == null ) {
+                                sameExceptions = mw.exceptionCount == 0;
+                            } else {
+                                if ( exceptions.length == mw.exceptionCount ) {
+                                    sameExceptions = true;
+                                    for ( j = exceptions.length - 1; j >= 0; --j ) {
+                                        w -= 2;
+                                        if ( mw.exceptions[j] != readUnsignedShort( w ) ) {
+                                            sameExceptions = false;
+                                            break;
+                                        }
+                                    }
+                                }
+                            }
+                            if ( sameExceptions ) {
+                                /*
+                                 * we do not copy directly the code into
+                                 * MethodWriter to save a byte array copy
+                                 * operation. The real copy will be done in
+                                 * ClassWriter.toByteArray().
+                                 */
+                                mw.classReaderOffset = u0;
+                                mw.classReaderLength = u - u0;
+                                continue;
+                            }
+                        }
+                    }
+                }
+                if ( dann != 0 ) {
+                    final AnnotationVisitor dv = mv.visitAnnotationDefault();
+                    readAnnotationValue( dann,
+                                         c,
+                                         null,
+                                         dv );
+                    dv.visitEnd();
+                }
+                for ( j = 1; j >= 0; --j ) {
+                    w = j == 0 ? ianns : anns;
+                    if ( w != 0 ) {
+                        k = readUnsignedShort( w );
+                        w += 2;
+                        for ( ; k > 0; --k ) {
+                            desc = readUTF8( w,
+                                             c );
+                            w += 2;
+                            w = readAnnotationValues( w,
+                                                      c,
+                                                      mv.visitAnnotation( desc,
+                                                                          j != 0 ) );
+                        }
+                    }
+                }
+                if ( mpanns != 0 ) {
+                    readParameterAnnotations( mpanns,
+                                              c,
+                                              true,
+                                              mv );
+                }
+                if ( impanns != 0 ) {
+                    readParameterAnnotations( impanns,
+                                              c,
+                                              false,
+                                              mv );
+                }
+                while ( cattrs != null ) {
+                    attr = cattrs.next;
+                    cattrs.next = null;
+                    mv.visitAttribute( cattrs );
+                    cattrs = attr;
+                }
+            }
+
+            if ( mv != null && v != 0 ) {
+                final int maxStack = readUnsignedShort( v );
+                final int maxLocals = readUnsignedShort( v + 2 );
+                final int codeLength = readInt( v + 4 );
+                v += 8;
+
+                final int codeStart = v;
+                final int codeEnd = v + codeLength;
+
+                mv.visitCode();
+
+                // 1st phase: finds the labels
+                int label;
+                final Label[] labels = new Label[codeLength + 1];
+                while ( v < codeEnd ) {
+                    int opcode = b[v] & 0xFF;
+                    switch ( ClassWriter.TYPE[opcode] ) {
+                        case ClassWriter.NOARG_INSN :
+                        case ClassWriter.IMPLVAR_INSN :
+                            v += 1;
+                            break;
+                        case ClassWriter.LABEL_INSN :
+                            label = v - codeStart + readShort( v + 1 );
+                            if ( labels[label] == null ) {
+                                labels[label] = new Label();
+                            }
+                            v += 3;
+                            break;
+                        case ClassWriter.LABELW_INSN :
+                            label = v - codeStart + readInt( v + 1 );
+                            if ( labels[label] == null ) {
+                                labels[label] = new Label();
+                            }
+                            v += 5;
+                            break;
+                        case ClassWriter.WIDE_INSN :
+                            opcode = b[v + 1] & 0xFF;
+                            if ( opcode == Opcodes.IINC ) {
+                                v += 6;
+                            } else {
+                                v += 4;
+                            }
+                            break;
+                        case ClassWriter.TABL_INSN :
+                            // skips 0 to 3 padding bytes
+                            w = v - codeStart;
+                            v = v + 4 - (w & 3);
+                            // reads instruction
+                            label = w + readInt( v );
+                            v += 4;
+                            if ( labels[label] == null ) {
+                                labels[label] = new Label();
+                            }
+                            j = readInt( v );
+                            v += 4;
+                            j = readInt( v ) - j + 1;
+                            v += 4;
+                            for ( ; j > 0; --j ) {
+                                label = w + readInt( v );
+                                v += 4;
+                                if ( labels[label] == null ) {
+                                    labels[label] = new Label();
+                                }
+                            }
+                            break;
+                        case ClassWriter.LOOK_INSN :
+                            // skips 0 to 3 padding bytes
+                            w = v - codeStart;
+                            v = v + 4 - (w & 3);
+                            // reads instruction
+                            label = w + readInt( v );
+                            v += 4;
+                            if ( labels[label] == null ) {
+                                labels[label] = new Label();
+                            }
+                            j = readInt( v );
+                            v += 4;
+                            for ( ; j > 0; --j ) {
+                                v += 4; // skips key
+                                label = w + readInt( v );
+                                v += 4;
+                                if ( labels[label] == null ) {
+                                    labels[label] = new Label();
+                                }
+                            }
+                            break;
+                        case ClassWriter.VAR_INSN :
+                        case ClassWriter.SBYTE_INSN :
+                        case ClassWriter.LDC_INSN :
+                            v += 2;
+                            break;
+                        case ClassWriter.SHORT_INSN :
+                        case ClassWriter.LDCW_INSN :
+                        case ClassWriter.FIELDORMETH_INSN :
+                        case ClassWriter.TYPE_INSN :
+                        case ClassWriter.IINC_INSN :
+                            v += 3;
+                            break;
+                        case ClassWriter.ITFMETH_INSN :
+                            v += 5;
+                            break;
+                        // case MANA_INSN:
+                        default :
+                            v += 4;
+                            break;
+                    }
+                }
+                // parses the try catch entries
+                j = readUnsignedShort( v );
+                v += 2;
+                for ( ; j > 0; --j ) {
+                    label = readUnsignedShort( v );
+                    Label start = labels[label];
+                    if ( start == null ) {
+                        labels[label] = start = new Label();
+                    }
+                    label = readUnsignedShort( v + 2 );
+                    Label end = labels[label];
+                    if ( end == null ) {
+                        labels[label] = end = new Label();
+                    }
+                    label = readUnsignedShort( v + 4 );
+                    Label handler = labels[label];
+                    if ( handler == null ) {
+                        labels[label] = handler = new Label();
+                    }
+
+                    final int type = readUnsignedShort( v + 6 );
+                    if ( type == 0 ) {
+                        mv.visitTryCatchBlock( start,
+                                               end,
+                                               handler,
+                                               null );
+                    } else {
+                        mv.visitTryCatchBlock( start,
+                                               end,
+                                               handler,
+                                               readUTF8( this.items[type],
+                                                         c ) );
+                    }
+                    v += 8;
+                }
+                // parses the local variable, line number tables, and code
+                // attributes
+                int varTable = 0;
+                int varTypeTable = 0;
+                cattrs = null;
+                j = readUnsignedShort( v );
+                v += 2;
+                for ( ; j > 0; --j ) {
+                    attrName = readUTF8( v,
+                                         c );
+                    if ( attrName.equals( "LocalVariableTable" ) ) {
+                        if ( !skipDebug ) {
+                            varTable = v + 6;
+                            k = readUnsignedShort( v + 6 );
+                            w = v + 8;
+                            for ( ; k > 0; --k ) {
+                                label = readUnsignedShort( w );
+                                if ( labels[label] == null ) {
+                                    labels[label] = new Label();
+                                }
+                                label += readUnsignedShort( w + 2 );
+                                if ( labels[label] == null ) {
+                                    labels[label] = new Label();
+                                }
+                                w += 10;
+                            }
+                        }
+                    } else if ( attrName.equals( "LocalVariableTypeTable" ) ) {
+                        varTypeTable = v + 6;
+                    } else if ( attrName.equals( "LineNumberTable" ) ) {
+                        if ( !skipDebug ) {
+                            k = readUnsignedShort( v + 6 );
+                            w = v + 8;
+                            for ( ; k > 0; --k ) {
+                                label = readUnsignedShort( w );
+                                if ( labels[label] == null ) {
+                                    labels[label] = new Label();
+                                }
+                                labels[label].line = readUnsignedShort( w + 2 );
+                                w += 4;
+                            }
+                        }
+                    } else {
+                        for ( k = 0; k < attrs.length; ++k ) {
+                            if ( attrs[k].type.equals( attrName ) ) {
+                                attr = attrs[k].read( this,
+                                                      v + 6,
+                                                      readInt( v + 2 ),
+                                                      c,
+                                                      codeStart - 8,
+                                                      labels );
+                                if ( attr != null ) {
+                                    attr.next = cattrs;
+                                    cattrs = attr;
+                                }
+                            }
+                        }
+                    }
+                    v += 6 + readInt( v + 2 );
+                }
+
+                // 2nd phase: visits each instruction
+                v = codeStart;
+                Label l;
+                while ( v < codeEnd ) {
+                    w = v - codeStart;
+                    l = labels[w];
+                    if ( l != null ) {
+                        mv.visitLabel( l );
+                        if ( !skipDebug && l.line > 0 ) {
+                            mv.visitLineNumber( l.line,
+                                                l );
+                        }
+                    }
+                    int opcode = b[v] & 0xFF;
+                    switch ( ClassWriter.TYPE[opcode] ) {
+                        case ClassWriter.NOARG_INSN :
+                            mv.visitInsn( opcode );
+                            v += 1;
+                            break;
+                        case ClassWriter.IMPLVAR_INSN :
+                            if ( opcode > Opcodes.ISTORE ) {
+                                opcode -= 59; // ISTORE_0
+                                mv.visitVarInsn( Opcodes.ISTORE + (opcode >> 2),
+                                                 opcode & 0x3 );
+                            } else {
+                                opcode -= 26; // ILOAD_0
+                                mv.visitVarInsn( Opcodes.ILOAD + (opcode >> 2),
+                                                 opcode & 0x3 );
+                            }
+                            v += 1;
+                            break;
+                        case ClassWriter.LABEL_INSN :
+                            mv.visitJumpInsn( opcode,
+                                              labels[w + readShort( v + 1 )] );
+                            v += 3;
+                            break;
+                        case ClassWriter.LABELW_INSN :
+                            mv.visitJumpInsn( opcode - 33,
+                                              labels[w + readInt( v + 1 )] );
+                            v += 5;
+                            break;
+                        case ClassWriter.WIDE_INSN :
+                            opcode = b[v + 1] & 0xFF;
+                            if ( opcode == Opcodes.IINC ) {
+                                mv.visitIincInsn( readUnsignedShort( v + 2 ),
+                                                  readShort( v + 4 ) );
+                                v += 6;
+                            } else {
+                                mv.visitVarInsn( opcode,
+                                                 readUnsignedShort( v + 2 ) );
+                                v += 4;
+                            }
+                            break;
+                        case ClassWriter.TABL_INSN :
+                            // skips 0 to 3 padding bytes
+                            v = v + 4 - (w & 3);
+                            // reads instruction
+                            label = w + readInt( v );
+                            v += 4;
+                            final int min = readInt( v );
+                            v += 4;
+                            final int max = readInt( v );
+                            v += 4;
+                            final Label[] table = new Label[max - min + 1];
+                            for ( j = 0; j < table.length; ++j ) {
+                                table[j] = labels[w + readInt( v )];
+                                v += 4;
+                            }
+                            mv.visitTableSwitchInsn( min,
+                                                     max,
+                                                     labels[label],
+                                                     table );
+                            break;
+                        case ClassWriter.LOOK_INSN :
+                            // skips 0 to 3 padding bytes
+                            v = v + 4 - (w & 3);
+                            // reads instruction
+                            label = w + readInt( v );
+                            v += 4;
+                            j = readInt( v );
+                            v += 4;
+                            final int[] keys = new int[j];
+                            final Label[] values = new Label[j];
+                            for ( j = 0; j < keys.length; ++j ) {
+                                keys[j] = readInt( v );
+                                v += 4;
+                                values[j] = labels[w + readInt( v )];
+                                v += 4;
+                            }
+                            mv.visitLookupSwitchInsn( labels[label],
+                                                      keys,
+                                                      values );
+                            break;
+                        case ClassWriter.VAR_INSN :
+                            mv.visitVarInsn( opcode,
+                                             b[v + 1] & 0xFF );
+                            v += 2;
+                            break;
+                        case ClassWriter.SBYTE_INSN :
+                            mv.visitIntInsn( opcode,
+                                             b[v + 1] );
+                            v += 2;
+                            break;
+                        case ClassWriter.SHORT_INSN :
+                            mv.visitIntInsn( opcode,
+                                             readShort( v + 1 ) );
+                            v += 3;
+                            break;
+                        case ClassWriter.LDC_INSN :
+                            mv.visitLdcInsn( readConst( b[v + 1] & 0xFF,
+                                                        c ) );
+                            v += 2;
+                            break;
+                        case ClassWriter.LDCW_INSN :
+                            mv.visitLdcInsn( readConst( readUnsignedShort( v + 1 ),
+                                                        c ) );
+                            v += 3;
+                            break;
+                        case ClassWriter.FIELDORMETH_INSN :
+                        case ClassWriter.ITFMETH_INSN :
+                            int cpIndex = this.items[readUnsignedShort( v + 1 )];
+                            final String iowner = readClass( cpIndex,
+                                                             c );
+                            cpIndex = this.items[readUnsignedShort( cpIndex + 2 )];
+                            final String iname = readUTF8( cpIndex,
+                                                           c );
+                            final String idesc = readUTF8( cpIndex + 2,
+                                                           c );
+                            if ( opcode < Opcodes.INVOKEVIRTUAL ) {
+                                mv.visitFieldInsn( opcode,
+                                                   iowner,
+                                                   iname,
+                                                   idesc );
+                            } else {
+                                mv.visitMethodInsn( opcode,
+                                                    iowner,
+                                                    iname,
+                                                    idesc );
+                            }
+                            if ( opcode == Opcodes.INVOKEINTERFACE ) {
+                                v += 5;
+                            } else {
+                                v += 3;
+                            }
+                            break;
+                        case ClassWriter.TYPE_INSN :
+                            mv.visitTypeInsn( opcode,
+                                              readClass( v + 1,
+                                                         c ) );
+                            v += 3;
+                            break;
+                        case ClassWriter.IINC_INSN :
+                            mv.visitIincInsn( b[v + 1] & 0xFF,
+                                              b[v + 2] );
+                            v += 3;
+                            break;
+                        // case MANA_INSN:
+                        default :
+                            mv.visitMultiANewArrayInsn( readClass( v + 1,
+                                                                   c ),
+                                                        b[v + 3] & 0xFF );
+                            v += 4;
+                            break;
+                    }
+                }
+                l = labels[codeEnd - codeStart];
+                if ( l != null ) {
+                    mv.visitLabel( l );
+                }
+
+                // visits the local variable tables
+                if ( !skipDebug && varTable != 0 ) {
+                    int[] typeTable = null;
+                    if ( varTypeTable != 0 ) {
+                        w = varTypeTable;
+                        k = readUnsignedShort( w ) * 3;
+                        w += 2;
+                        typeTable = new int[k];
+                        while ( k > 0 ) {
+                            typeTable[--k] = w + 6; // signature
+                            typeTable[--k] = readUnsignedShort( w + 8 ); // index
+                            typeTable[--k] = readUnsignedShort( w ); // start
+                            w += 10;
+                        }
+                    }
+                    w = varTable;
+                    k = readUnsignedShort( w );
+                    w += 2;
+                    for ( ; k > 0; --k ) {
+                        final int start = readUnsignedShort( w );
+                        final int length = readUnsignedShort( w + 2 );
+                        final int index = readUnsignedShort( w + 8 );
+                        String vsignature = null;
+                        if ( typeTable != null ) {
+                            for ( int a = 0; a < typeTable.length; a += 3 ) {
+                                if ( typeTable[a] == start && typeTable[a + 1] == index ) {
+                                    vsignature = readUTF8( typeTable[a + 2],
+                                                           c );
+                                    break;
+                                }
+                            }
+                        }
+                        mv.visitLocalVariable( readUTF8( w + 4,
+                                                         c ),
+                                               readUTF8( w + 6,
+                                                         c ),
+                                               vsignature,
+                                               labels[start],
+                                               labels[start + length],
+                                               index );
+                        w += 10;
+                    }
+                }
+                // visits the other attributes
+                while ( cattrs != null ) {
+                    attr = cattrs.next;
+                    cattrs.next = null;
+                    mv.visitAttribute( cattrs );
+                    cattrs = attr;
+                }
+                // visits the min stack and min locals values
+                mv.visitMaxs( maxStack,
+                              maxLocals );
+            }
+
+            if ( mv != null ) {
+                mv.visitEnd();
+            }
+        }
+
+        // visits the end of the class
+        classVisitor.visitEnd();
+    }
+
+    /**
+     * Reads parameter annotations and makes the given visitor visit them.
+     * 
+     * @param v start offset in {@link #b b} of the annotations to be read.
+     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+     *        {@link #readClass(int,char[]) readClass} or
+     *        {@link #readConst readConst}.
+     * @param visible <tt>true</tt> if the annotations to be read are visible
+     *        at runtime.
+     * @param mv the visitor that must visit the annotations.
+     */
+    private void readParameterAnnotations(int v,
+                                          final char[] buf,
+                                          final boolean visible,
+                                          final MethodVisitor mv) {
+        final int n = this.b[v++] & 0xFF;
+        for ( int i = 0; i < n; ++i ) {
+            int j = readUnsignedShort( v );
+            v += 2;
+            for ( ; j > 0; --j ) {
+                final String desc = readUTF8( v,
+                                              buf );
+                v += 2;
+                final AnnotationVisitor av = mv.visitParameterAnnotation( i,
+                                                                          desc,
+                                                                          visible );
+                v = readAnnotationValues( v,
+                                          buf,
+                                          av );
+            }
+        }
+    }
+
+    /**
+     * Reads the values of an annotation and makes the given visitor visit them.
+     * 
+     * @param v the start offset in {@link #b b} of the values to be read
+     *        (including the unsigned short that gives the number of values).
+     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+     *        {@link #readClass(int,char[]) readClass} or
+     *        {@link #readConst readConst}.
+     * @param av the visitor that must visit the values.
+     * @return the end offset of the annotations values.
+     */
+    private int readAnnotationValues(int v,
+                                     final char[] buf,
+                                     final AnnotationVisitor av) {
+        int i = readUnsignedShort( v );
+        v += 2;
+        for ( ; i > 0; --i ) {
+            final String name = readUTF8( v,
+                                          buf );
+            v += 2;
+            v = readAnnotationValue( v,
+                                     buf,
+                                     name,
+                                     av );
+        }
+        av.visitEnd();
+        return v;
+    }
+
+    /**
+     * Reads a value of an annotation and makes the given visitor visit it.
+     * 
+     * @param v the start offset in {@link #b b} of the value to be read (<i>not
+     *        including the value name constant pool index</i>).
+     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+     *        {@link #readClass(int,char[]) readClass} or
+     *        {@link #readConst readConst}.
+     * @param name the name of the value to be read.
+     * @param av the visitor that must visit the value.
+     * @return the end offset of the annotation value.
+     */
+    private int readAnnotationValue(int v,
+                                    final char[] buf,
+                                    final String name,
+                                    final AnnotationVisitor av) {
+        int i;
+        switch ( readByte( v++ ) ) {
+            case 'I' : // pointer to CONSTANT_Integer
+            case 'J' : // pointer to CONSTANT_Long
+            case 'F' : // pointer to CONSTANT_Float
+            case 'D' : // pointer to CONSTANT_Double
+                av.visit( name,
+                          readConst( readUnsignedShort( v ),
+                                     buf ) );
+                v += 2;
+                break;
+            case 'B' : // pointer to CONSTANT_Byte
+                av.visit( name,
+                          new Byte( (byte) readInt( this.items[readUnsignedShort( v )] ) ) );
+                v += 2;
+                break;
+            case 'Z' : // pointer to CONSTANT_Boolean
+                final boolean b = readInt( this.items[readUnsignedShort( v )] ) == 0;
+                av.visit( name,
+                          b ? Boolean.FALSE : Boolean.TRUE );
+                v += 2;
+                break;
+            case 'S' : // pointer to CONSTANT_Short
+                av.visit( name,
+                          new Short( (short) readInt( this.items[readUnsignedShort( v )] ) ) );
+                v += 2;
+                break;
+            case 'C' : // pointer to CONSTANT_Char
+                av.visit( name,
+                          new Character( (char) readInt( this.items[readUnsignedShort( v )] ) ) );
+                v += 2;
+                break;
+            case 's' : // pointer to CONSTANT_Utf8
+                av.visit( name,
+                          readUTF8( v,
+                                    buf ) );
+                v += 2;
+                break;
+            case 'e' : // enum_const_value
+                av.visitEnum( name,
+                              readUTF8( v,
+                                        buf ),
+                              readUTF8( v + 2,
+                                        buf ) );
+                v += 4;
+                break;
+            case 'c' : // class_info
+                av.visit( name,
+                          Type.getType( readUTF8( v,
+                                                  buf ) ) );
+                v += 2;
+                break;
+            case '@' : // annotation_value
+                final String desc = readUTF8( v,
+                                              buf );
+                v += 2;
+                v = readAnnotationValues( v,
+                                          buf,
+                                          av.visitAnnotation( name,
+                                                              desc ) );
+                break;
+            case '[' : // array_value
+                final int size = readUnsignedShort( v );
+                v += 2;
+                if ( size == 0 ) {
+                    av.visitArray( name ).visitEnd();
+                    return v;
+                }
+                switch ( readByte( v++ ) ) {
+                    case 'B' :
+                        final byte[] bv = new byte[size];
+                        for ( i = 0; i < size; i++ ) {
+                            bv[i] = (byte) readInt( this.items[readUnsignedShort( v )] );
+                            v += 3;
+                        }
+                        av.visit( name,
+                                  bv );
+                        --v;
+                        break;
+                    case 'Z' :
+                        final boolean[] zv = new boolean[size];
+                        for ( i = 0; i < size; i++ ) {
+                            zv[i] = readInt( this.items[readUnsignedShort( v )] ) != 0;
+                            v += 3;
+                        }
+                        av.visit( name,
+                                  zv );
+                        --v;
+                        break;
+                    case 'S' :
+                        final short[] sv = new short[size];
+                        for ( i = 0; i < size; i++ ) {
+                            sv[i] = (short) readInt( this.items[readUnsignedShort( v )] );
+                            v += 3;
+                        }
+                        av.visit( name,
+                                  sv );
+                        --v;
+                        break;
+                    case 'C' :
+                        final char[] cv = new char[size];
+                        for ( i = 0; i < size; i++ ) {
+                            cv[i] = (char) readInt( this.items[readUnsignedShort( v )] );
+                            v += 3;
+                        }
+                        av.visit( name,
+                                  cv );
+                        --v;
+                        break;
+                    case 'I' :
+                        final int[] iv = new int[size];
+                        for ( i = 0; i < size; i++ ) {
+                            iv[i] = readInt( this.items[readUnsignedShort( v )] );
+                            v += 3;
+                        }
+                        av.visit( name,
+                                  iv );
+                        --v;
+                        break;
+                    case 'J' :
+                        final long[] lv = new long[size];
+                        for ( i = 0; i < size; i++ ) {
+                            lv[i] = readLong( this.items[readUnsignedShort( v )] );
+                            v += 3;
+                        }
+                        av.visit( name,
+                                  lv );
+                        --v;
+                        break;
+                    case 'F' :
+                        final float[] fv = new float[size];
+                        for ( i = 0; i < size; i++ ) {
+                            fv[i] = Float.intBitsToFloat( readInt( this.items[readUnsignedShort( v )] ) );
+                            v += 3;
+                        }
+                        av.visit( name,
+                                  fv );
+                        --v;
+                        break;
+                    case 'D' :
+                        final double[] dv = new double[size];
+                        for ( i = 0; i < size; i++ ) {
+                            dv[i] = Double.longBitsToDouble( readLong( this.items[readUnsignedShort( v )] ) );
+                            v += 3;
+                        }
+                        av.visit( name,
+                                  dv );
+                        --v;
+                        break;
+                    default :
+                        v--;
+                        final AnnotationVisitor aav = av.visitArray( name );
+                        for ( i = size; i > 0; --i ) {
+                            v = readAnnotationValue( v,
+                                                     buf,
+                                                     null,
+                                                     aav );
+                        }
+                        aav.visitEnd();
+                }
+        }
+        return v;
+    }
+
+    /**
+     * Reads an attribute in {@link #b b}.
+     * 
+     * @param attrs prototypes of the attributes that must be parsed during the
+     *        visit of the class. Any attribute whose type is not equal to the
+     *        type of one the prototypes is ignored (i.e. an empty
+     *        {@link Attribute} instance is returned).
+     * @param type the type of the attribute.
+     * @param off index of the first byte of the attribute's content in
+     *        {@link #b b}. The 6 attribute header bytes, containing the type
+     *        and the length of the attribute, are not taken into account here
+     *        (they have already been read).
+     * @param len the length of the attribute's content.
+     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+     *        {@link #readClass(int,char[]) readClass} or
+     *        {@link #readConst readConst}.
+     * @param codeOff index of the first byte of code's attribute content in
+     *        {@link #b b}, or -1 if the attribute to be read is not a code
+     *        attribute. The 6 attribute header bytes, containing the type and
+     *        the length of the attribute, are not taken into account here.
+     * @param labels the labels of the method's code, or <tt>null</tt> if the
+     *        attribute to be read is not a code attribute.
+     * @return the attribute that has been read, or <tt>null</tt> to skip this
+     *         attribute.
+     */
+    private Attribute readAttribute(final Attribute[] attrs,
+                                    final String type,
+                                    final int off,
+                                    final int len,
+                                    final char[] buf,
+                                    final int codeOff,
+                                    final Label[] labels) {
+        for ( int i = 0; i < attrs.length; ++i ) {
+            if ( attrs[i].type.equals( type ) ) {
+                return attrs[i].read( this,
+                                      off,
+                                      len,
+                                      buf,
+                                      codeOff,
+                                      labels );
+            }
+        }
+        return new Attribute( type ).read( this,
+                                           off,
+                                           len,
+                                           null,
+                                           -1,
+                                           null );
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods: low level parsing
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns the start index of the constant pool item in {@link #b b}, plus
+     * one. <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     * 
+     * @param item the index a constant pool item.
+     * @return the start index of the constant pool item in {@link #b b}, plus
+     *         one.
+     */
+    public int getItem(final int item) {
+        return this.items[item];
+    }
+
+    /**
+     * Reads a byte value in {@link #b b}. <i>This method is intended for
+     * {@link Attribute} sub classes, and is normally not needed by class
+     * generators or adapters.</i>
+     * 
+     * @param index the start index of the value to be read in {@link #b b}.
+     * @return the read value.
+     */
+    public int readByte(final int index) {
+        return this.b[index] & 0xFF;
+    }
+
+    /**
+     * Reads an unsigned short value in {@link #b b}. <i>This method is
+     * intended for {@link Attribute} sub classes, and is normally not needed by
+     * class generators or adapters.</i>
+     * 
+     * @param index the start index of the value to be read in {@link #b b}.
+     * @return the read value.
+     */
+    public int readUnsignedShort(final int index) {
+        final byte[] b = this.b;
+        return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
+    }
+
+    /**
+     * Reads a signed short value in {@link #b b}. <i>This method is intended
+     * for {@link Attribute} sub classes, and is normally not needed by class
+     * generators or adapters.</i>
+     * 
+     * @param index the start index of the value to be read in {@link #b b}.
+     * @return the read value.
+     */
+    public short readShort(final int index) {
+        final byte[] b = this.b;
+        return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
+    }
+
+    /**
+     * Reads a signed int value in {@link #b b}. <i>This method is intended for
+     * {@link Attribute} sub classes, and is normally not needed by class
+     * generators or adapters.</i>
+     * 
+     * @param index the start index of the value to be read in {@link #b b}.
+     * @return the read value.
+     */
+    public int readInt(final int index) {
+        final byte[] b = this.b;
+        return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16) | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
+    }
+
+    /**
+     * Reads a signed long value in {@link #b b}. <i>This method is intended
+     * for {@link Attribute} sub classes, and is normally not needed by class
+     * generators or adapters.</i>
+     * 
+     * @param index the start index of the value to be read in {@link #b b}.
+     * @return the read value.
+     */
+    public long readLong(final int index) {
+        final long l1 = readInt( index );
+        final long l0 = readInt( index + 4 ) & 0xFFFFFFFFL;
+        return (l1 << 32) | l0;
+    }
+
+    /**
+     * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method
+     * is intended for {@link Attribute} sub classes, and is normally not needed
+     * by class generators or adapters.</i>
+     * 
+     * @param index the start index of an unsigned short value in {@link #b b},
+     *        whose value is the index of an UTF8 constant pool item.
+     * @param buf buffer to be used to read the item. This buffer must be
+     *        sufficiently large. It is not automatically resized.
+     * @return the String corresponding to the specified UTF8 item.
+     */
+    public String readUTF8(int index,
+                           final char[] buf) {
+        final int item = readUnsignedShort( index );
+        final String s = this.strings[item];
+        if ( s != null ) {
+            return s;
+        }
+        index = this.items[item];
+        return this.strings[item] = readUTF( index + 2,
+                                             readUnsignedShort( index ),
+                                             buf );
+    }
+
+    /**
+     * Reads UTF8 string in {@link #b b}.
+     * 
+     * @param index start offset of the UTF8 string to be read.
+     * @param utfLen length of the UTF8 string to be read.
+     * @param buf buffer to be used to read the string. This buffer must be
+     *        sufficiently large. It is not automatically resized.
+     * @return the String corresponding to the specified UTF8 string.
+     */
+    private String readUTF(int index,
+                           final int utfLen,
+                           final char[] buf) {
+        final int endIndex = index + utfLen;
+        final byte[] b = this.b;
+        int strLen = 0;
+        int c, d, e;
+        while ( index < endIndex ) {
+            c = b[index++] & 0xFF;
+            switch ( c >> 4 ) {
+                case 0 :
+                case 1 :
+                case 2 :
+                case 3 :
+                case 4 :
+                case 5 :
+                case 6 :
+                case 7 :
+                    // 0xxxxxxx
+                    buf[strLen++] = (char) c;
+                    break;
+                case 12 :
+                case 13 :
+                    // 110x xxxx 10xx xxxx
+                    d = b[index++];
+                    buf[strLen++] = (char) (((c & 0x1F) << 6) | (d & 0x3F));
+                    break;
+                default :
+                    // 1110 xxxx 10xx xxxx 10xx xxxx
+                    d = b[index++];
+                    e = b[index++];
+                    buf[strLen++] = (char) (((c & 0x0F) << 12) | ((d & 0x3F) << 6) | (e & 0x3F));
+                    break;
+            }
+        }
+        return new String( buf,
+                           0,
+                           strLen );
+    }
+
+    /**
+     * Reads a class constant pool item in {@link #b b}. <i>This method is
+     * intended for {@link Attribute} sub classes, and is normally not needed by
+     * class generators or adapters.</i>
+     * 
+     * @param index the start index of an unsigned short value in {@link #b b},
+     *        whose value is the index of a class constant pool item.
+     * @param buf buffer to be used to read the item. This buffer must be
+     *        sufficiently large. It is not automatically resized.
+     * @return the String corresponding to the specified class item.
+     */
+    public String readClass(final int index,
+                            final char[] buf) {
+        // computes the start index of the CONSTANT_Class item in b
+        // and reads the CONSTANT_Utf8 item designated by
+        // the first two bytes of this CONSTANT_Class item
+        return readUTF8( this.items[readUnsignedShort( index )],
+                         buf );
+    }
+
+    /**
+     * Reads a numeric or string constant pool item in {@link #b b}. <i>This
+     * method is intended for {@link Attribute} sub classes, and is normally not
+     * needed by class generators or adapters.</i>
+     * 
+     * @param item the index of a constant pool item.
+     * @param buf buffer to be used to read the item. This buffer must be
+     *        sufficiently large. It is not automatically resized.
+     * @return the {@link Integer}, {@link Float}, {@link Long},
+     *         {@link Double}, {@link String} or {@link Type} corresponding to
+     *         the given constant pool item.
+     */
+    public Object readConst(final int item,
+                            final char[] buf) {
+        final int index = this.items[item];
+        switch ( this.b[index - 1] ) {
+            case ClassWriter.INT :
+                return new Integer( readInt( index ) );
+            case ClassWriter.FLOAT :
+                return new Float( Float.intBitsToFloat( readInt( index ) ) );
+            case ClassWriter.LONG :
+                return new Long( readLong( index ) );
+            case ClassWriter.DOUBLE :
+                return new Double( Double.longBitsToDouble( readLong( index ) ) );
+            case ClassWriter.CLASS :
+                final String s = readUTF8( index,
+                                           buf );
+                return Type.getType( s.charAt( 0 ) == '[' ? s : "L" + s + ";" );
+                // case ClassWriter.STR:
+            default :
+                return readUTF8( index,
+                                 buf );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/ClassVisitor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/ClassVisitor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/ClassVisitor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,195 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm;
+
+/**
+ * A visitor to visit a Java class. The methods of this interface must be called
+ * in the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
+ * <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
+ * <tt>visitAttribute</tt> )* (<tt>visitInnerClass</tt> |
+ * <tt>visitField</tt> | <tt>visitMethod</tt> )* <tt>visitEnd</tt>.
+ * 
+ * @author Eric Bruneton
+ */
+public interface ClassVisitor {
+
+    /**
+     * Visits the header of the class.
+     * 
+     * @param version the class version.
+     * @param access the class's access flags (see {@link Opcodes}). This
+     *        parameter also indicates if the class is deprecated.
+     * @param name the internal name of the class (see
+     *        {@link Type#getInternalName() getInternalName}).
+     * @param signature the signature of this class. May be <tt>null</tt> if
+     *        the class is not a generic one, and does not extend or implement
+     *        generic classes or interfaces.
+     * @param superName the internal of name of the super class (see
+     *        {@link Type#getInternalName() getInternalName}). For interfaces,
+     *        the super class is {@link Object}. May be <tt>null</tt>, but
+     *        only for the {@link Object} class.
+     * @param interfaces the internal names of the class's interfaces (see
+     *        {@link Type#getInternalName() getInternalName}). May be
+     *        <tt>null</tt>.
+     */
+    void visit(int version,
+               int access,
+               String name,
+               String signature,
+               String superName,
+               String[] interfaces);
+
+    /**
+     * Visits the source of the class.
+     * 
+     * @param source the name of the source file from which the class was
+     *        compiled. May be <tt>null</tt>.
+     * @param debug additional debug information to compute the correspondance
+     *        between source and compiled elements of the class. May be
+     *        <tt>null</tt>.
+     */
+    void visitSource(String source,
+                     String debug);
+
+    /**
+     * Visits the enclosing class of the class. This method must be called only
+     * if the class has an enclosing class.
+     * 
+     * @param owner internal name of the enclosing class of the class.
+     * @param name the name of the method that contains the class, or
+     *        <tt>null</tt> if the class is not enclosed in a method of its
+     *        enclosing class.
+     * @param desc the descriptor of the method that contains the class, or
+     *        <tt>null</tt> if the class is not enclosed in a method of its
+     *        enclosing class.
+     */
+    void visitOuterClass(String owner,
+                         String name,
+                         String desc);
+
+    /**
+     * Visits an annotation of the class.
+     * 
+     * @param desc the class descriptor of the annotation class.
+     * @param visible <tt>true</tt> if the annotation is visible at runtime.
+     * @return a non null visitor to visit the annotation values.
+     */
+    AnnotationVisitor visitAnnotation(String desc,
+                                      boolean visible);
+
+    /**
+     * Visits a non standard attribute of the class.
+     * 
+     * @param attr an attribute.
+     */
+    void visitAttribute(Attribute attr);
+
+    /**
+     * Visits information about an inner class. This inner class is not
+     * necessarily a member of the class being visited.
+     * 
+     * @param name the internal name of an inner class (see
+     *        {@link Type#getInternalName() getInternalName}).
+     * @param outerName the internal name of the class to which the inner class
+     *        belongs (see {@link Type#getInternalName() getInternalName}). May
+     *        be <tt>null</tt>.
+     * @param innerName the (simple) name of the inner class inside its
+     *        enclosing class. May be <tt>null</tt> for anonymous inner
+     *        classes.
+     * @param access the access flags of the inner class as originally declared
+     *        in the enclosing class.
+     */
+    void visitInnerClass(String name,
+                         String outerName,
+                         String innerName,
+                         int access);
+
+    /**
+     * Visits a field of the class.
+     * 
+     * @param access the field's access flags (see {@link Opcodes}). This
+     *        parameter also indicates if the field is synthetic and/or
+     *        deprecated.
+     * @param name the field's name.
+     * @param desc the field's descriptor (see {@link Type Type}).
+     * @param signature the field's signature. May be <tt>null</tt> if the
+     *        field's type does not use generic types.
+     * @param value the field's initial value. This parameter, which may be
+     *        <tt>null</tt> if the field does not have an initial value, must
+     *        be an {@link Integer}, a {@link Float}, a {@link Long}, a
+     *        {@link Double} or a {@link String} (for <tt>int</tt>,
+     *        <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields
+     *        respectively). <i>This parameter is only used for static fields</i>.
+     *        Its value is ignored for non static fields, which must be
+     *        initialized through bytecode instructions in constructors or
+     *        methods.
+     * @return a visitor to visit field annotations and attributes, or
+     *         <tt>null</tt> if this class visitor is not interested in
+     *         visiting these annotations and attributes.
+     */
+    FieldVisitor visitField(int access,
+                            String name,
+                            String desc,
+                            String signature,
+                            Object value);
+
+    /**
+     * Visits a method of the class. This method <i>must</i> return a new
+     * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is
+     * called, i.e., it should not return a previously returned visitor.
+     * 
+     * @param access the method's access flags (see {@link Opcodes}). This
+     *        parameter also indicates if the method is synthetic and/or
+     *        deprecated.
+     * @param name the method's name.
+     * @param desc the method's descriptor (see {@link Type Type}).
+     * @param signature the method's signature. May be <tt>null</tt> if the
+     *        method parameters, return type and exceptions do not use generic
+     *        types.
+     * @param exceptions the internal names of the method's exception classes
+     *        (see {@link Type#getInternalName() getInternalName}). May be
+     *        <tt>null</tt>.
+     * @return an object to visit the byte code of the method, or <tt>null</tt>
+     *         if this class visitor is not interested in visiting the code of
+     *         this method.
+     */
+    MethodVisitor visitMethod(int access,
+                              String name,
+                              String desc,
+                              String signature,
+                              String[] exceptions);
+
+    /**
+     * Visits the end of the class. This method, which is the last one to be
+     * called, is used to inform the visitor that all the fields and methods of
+     * the class have been visited.
+     */
+    void visitEnd();
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/ClassWriter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/ClassWriter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/ClassWriter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,1213 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm;
+
+/**
+ * A {@link ClassVisitor} that generates classes in bytecode form. More
+ * precisely this visitor generates a byte array conforming to the Java class
+ * file format. It can be used alone, to generate a Java class "from scratch",
+ * or with one or more {@link ClassReader ClassReader} and adapter class visitor
+ * to generate a modified class from one or more existing Java classes.
+ * 
+ * @author Eric Bruneton
+ */
+public class ClassWriter
+    implements
+    ClassVisitor {
+
+    /**
+     * The type of instructions without any argument.
+     */
+    final static int         NOARG_INSN       = 0;
+
+    /**
+     * The type of instructions with an signed byte argument.
+     */
+    final static int         SBYTE_INSN       = 1;
+
+    /**
+     * The type of instructions with an signed short argument.
+     */
+    final static int         SHORT_INSN       = 2;
+
+    /**
+     * The type of instructions with a local variable index argument.
+     */
+    final static int         VAR_INSN         = 3;
+
+    /**
+     * The type of instructions with an implicit local variable index argument.
+     */
+    final static int         IMPLVAR_INSN     = 4;
+
+    /**
+     * The type of instructions with a type descriptor argument.
+     */
+    final static int         TYPE_INSN        = 5;
+
+    /**
+     * The type of field and method invocations instructions.
+     */
+    final static int         FIELDORMETH_INSN = 6;
+
+    /**
+     * The type of the INVOKEINTERFACE instruction.
+     */
+    final static int         ITFMETH_INSN     = 7;
+
+    /**
+     * The type of instructions with a 2 bytes bytecode offset label.
+     */
+    final static int         LABEL_INSN       = 8;
+
+    /**
+     * The type of instructions with a 4 bytes bytecode offset label.
+     */
+    final static int         LABELW_INSN      = 9;
+
+    /**
+     * The type of the LDC instruction.
+     */
+    final static int         LDC_INSN         = 10;
+
+    /**
+     * The type of the LDC_W and LDC2_W instructions.
+     */
+    final static int         LDCW_INSN        = 11;
+
+    /**
+     * The type of the IINC instruction.
+     */
+    final static int         IINC_INSN        = 12;
+
+    /**
+     * The type of the TABLESWITCH instruction.
+     */
+    final static int         TABL_INSN        = 13;
+
+    /**
+     * The type of the LOOKUPSWITCH instruction.
+     */
+    final static int         LOOK_INSN        = 14;
+
+    /**
+     * The type of the MULTIANEWARRAY instruction.
+     */
+    final static int         MANA_INSN        = 15;
+
+    /**
+     * The type of the WIDE instruction.
+     */
+    final static int         WIDE_INSN        = 16;
+
+    /**
+     * The instruction types of all JVM opcodes.
+     */
+    static byte[]            TYPE;
+
+    /**
+     * The type of CONSTANT_Class constant pool items.
+     */
+    final static int         CLASS            = 7;
+
+    /**
+     * The type of CONSTANT_Fieldref constant pool items.
+     */
+    final static int         FIELD            = 9;
+
+    /**
+     * The type of CONSTANT_Methodref constant pool items.
+     */
+    final static int         METH             = 10;
+
+    /**
+     * The type of CONSTANT_InterfaceMethodref constant pool items.
+     */
+    final static int         IMETH            = 11;
+
+    /**
+     * The type of CONSTANT_String constant pool items.
+     */
+    final static int         STR              = 8;
+
+    /**
+     * The type of CONSTANT_Integer constant pool items.
+     */
+    final static int         INT              = 3;
+
+    /**
+     * The type of CONSTANT_Float constant pool items.
+     */
+    final static int         FLOAT            = 4;
+
+    /**
+     * The type of CONSTANT_Long constant pool items.
+     */
+    final static int         LONG             = 5;
+
+    /**
+     * The type of CONSTANT_Double constant pool items.
+     */
+    final static int         DOUBLE           = 6;
+
+    /**
+     * The type of CONSTANT_NameAndType constant pool items.
+     */
+    final static int         NAME_TYPE        = 12;
+
+    /**
+     * The type of CONSTANT_Utf8 constant pool items.
+     */
+    final static int         UTF8             = 1;
+
+    /**
+     * The class reader from which this class writer was constructed, if any.
+     */
+    ClassReader              cr;
+
+    /**
+     * Minor and major version numbers of the class to be generated.
+     */
+    int                      version;
+
+    /**
+     * Index of the next item to be added in the constant pool.
+     */
+    int                      index;
+
+    /**
+     * The constant pool of this class.
+     */
+    ByteVector               pool;
+
+    /**
+     * The constant pool's hash table data.
+     */
+    Item[]                   items;
+
+    /**
+     * The threshold of the constant pool's hash table.
+     */
+    int                      threshold;
+
+    /**
+     * A reusable key used to look for items in the hash {@link #items items}.
+     */
+    Item                     key;
+
+    /**
+     * A reusable key used to look for items in the hash {@link #items items}.
+     */
+    Item                     key2;
+
+    /**
+     * A reusable key used to look for items in the hash {@link #items items}.
+     */
+    Item                     key3;
+
+    /**
+     * The access flags of this class.
+     */
+    private int              access;
+
+    /**
+     * The constant pool item that contains the internal name of this class.
+     */
+    private int              name;
+
+    /**
+     * The constant pool item that contains the signature of this class.
+     */
+    private int              signature;
+
+    /**
+     * The constant pool item that contains the internal name of the super class
+     * of this class.
+     */
+    private int              superName;
+
+    /**
+     * Number of interfaces implemented or extended by this class or interface.
+     */
+    private int              interfaceCount;
+
+    /**
+     * The interfaces implemented or extended by this class or interface. More
+     * precisely, this array contains the indexes of the constant pool items
+     * that contain the internal names of these interfaces.
+     */
+    private int[]            interfaces;
+
+    /**
+     * The index of the constant pool item that contains the name of the source
+     * file from which this class was compiled.
+     */
+    private int              sourceFile;
+
+    /**
+     * The SourceDebug attribute of this class.
+     */
+    private ByteVector       sourceDebug;
+
+    /**
+     * The constant pool item that contains the name of the enclosing class of
+     * this class.
+     */
+    private int              enclosingMethodOwner;
+
+    /**
+     * The constant pool item that contains the name and descriptor of the
+     * enclosing method of this class.
+     */
+    private int              enclosingMethod;
+
+    /**
+     * The runtime visible annotations of this class.
+     */
+    private AnnotationWriter anns;
+
+    /**
+     * The runtime invisible annotations of this class.
+     */
+    private AnnotationWriter ianns;
+
+    /**
+     * The non standard attributes of this class.
+     */
+    private Attribute        attrs;
+
+    /**
+     * The number of entries in the InnerClasses attribute.
+     */
+    private int              innerClassesCount;
+
+    /**
+     * The InnerClasses attribute.
+     */
+    private ByteVector       innerClasses;
+
+    /**
+     * The fields of this class. These fields are stored in a linked list of
+     * {@link FieldWriter} objects, linked to each other by their
+     * {@link FieldWriter#next} field. This field stores the first element of
+     * this list.
+     */
+    FieldWriter              firstField;
+
+    /**
+     * The fields of this class. These fields are stored in a linked list of
+     * {@link FieldWriter} objects, linked to each other by their
+     * {@link FieldWriter#next} field. This field stores the last element of
+     * this list.
+     */
+    FieldWriter              lastField;
+
+    /**
+     * The methods of this class. These methods are stored in a linked list of
+     * {@link MethodWriter} objects, linked to each other by their
+     * {@link MethodWriter#next} field. This field stores the first element of
+     * this list.
+     */
+    MethodWriter             firstMethod;
+
+    /**
+     * The methods of this class. These methods are stored in a linked list of
+     * {@link MethodWriter} objects, linked to each other by their
+     * {@link MethodWriter#next} field. This field stores the last element of
+     * this list.
+     */
+    MethodWriter             lastMethod;
+
+    /**
+     * <tt>true</tt> if the maximum stack size and number of local variables
+     * must be automatically computed.
+     */
+    private boolean          computeMaxs;
+
+    // ------------------------------------------------------------------------
+    // Static initializer
+    // ------------------------------------------------------------------------
+
+    /**
+     * Computes the instruction types of JVM opcodes.
+     */
+    static {
+        int i;
+        final byte[] b = new byte[220];
+        final String s = "AAAAAAAAAAAAAAAABCKLLDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD" + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAIIIIIIIIIIIIIIIIDNOAA"
+                         + "AAAAGGGGGGGHAFBFAAFFAAQPIIJJIIIIIIIIIIIIIIIIII";
+        for ( i = 0; i < b.length; ++i ) {
+            b[i] = (byte) (s.charAt( i ) - 'A');
+        }
+        ClassWriter.TYPE = b;
+
+        // code to generate the above string
+        //
+        // // SBYTE_INSN instructions
+        // b[Constants.NEWARRAY] = SBYTE_INSN;
+        // b[Constants.BIPUSH] = SBYTE_INSN;
+        //
+        // // SHORT_INSN instructions
+        // b[Constants.SIPUSH] = SHORT_INSN;
+        //
+        // // (IMPL)VAR_INSN instructions
+        // b[Constants.RET] = VAR_INSN;
+        // for (i = Constants.ILOAD; i <= Constants.ALOAD; ++i) {
+        // b[i] = VAR_INSN;
+        // }
+        // for (i = Constants.ISTORE; i <= Constants.ASTORE; ++i) {
+        // b[i] = VAR_INSN;
+        // }
+        // for (i = 26; i <= 45; ++i) { // ILOAD_0 to ALOAD_3
+        // b[i] = IMPLVAR_INSN;
+        // }
+        // for (i = 59; i <= 78; ++i) { // ISTORE_0 to ASTORE_3
+        // b[i] = IMPLVAR_INSN;
+        // }
+        //
+        // // TYPE_INSN instructions
+        // b[Constants.NEW] = TYPE_INSN;
+        // b[Constants.ANEWARRAY] = TYPE_INSN;
+        // b[Constants.CHECKCAST] = TYPE_INSN;
+        // b[Constants.INSTANCEOF] = TYPE_INSN;
+        //
+        // // (Set)FIELDORMETH_INSN instructions
+        // for (i = Constants.GETSTATIC; i <= Constants.INVOKESTATIC; ++i) {
+        // b[i] = FIELDORMETH_INSN;
+        // }
+        // b[Constants.INVOKEINTERFACE] = ITFMETH_INSN;
+        //
+        // // LABEL(W)_INSN instructions
+        // for (i = Constants.IFEQ; i <= Constants.JSR; ++i) {
+        // b[i] = LABEL_INSN;
+        // }
+        // b[Constants.IFNULL] = LABEL_INSN;
+        // b[Constants.IFNONNULL] = LABEL_INSN;
+        // b[200] = LABELW_INSN; // GOTO_W
+        // b[201] = LABELW_INSN; // JSR_W
+        // // temporary opcodes used internally by ASM - see Label and
+        // MethodWriter
+        // for (i = 202; i < 220; ++i) {
+        // b[i] = LABEL_INSN;
+        // }
+        //
+        // // LDC(_W) instructions
+        // b[Constants.LDC] = LDC_INSN;
+        // b[19] = LDCW_INSN; // LDC_W
+        // b[20] = LDCW_INSN; // LDC2_W
+        //
+        // // special instructions
+        // b[Constants.IINC] = IINC_INSN;
+        // b[Constants.TABLESWITCH] = TABL_INSN;
+        // b[Constants.LOOKUPSWITCH] = LOOK_INSN;
+        // b[Constants.MULTIANEWARRAY] = MANA_INSN;
+        // b[196] = WIDE_INSN; // WIDE
+        //
+        // for (i = 0; i < b.length; ++i) {
+        // System.err.print((char)('A' + b[i]));
+        // }
+        // System.err.println();
+    }
+
+    // ------------------------------------------------------------------------
+    // Constructor
+    // ------------------------------------------------------------------------
+
+    /**
+     * Constructs a new {@link ClassWriter ClassWriter} object.
+     * 
+     * @param computeMaxs <tt>true</tt> if the maximum stack size and the
+     *        maximum number of local variables must be automatically computed.
+     *        If this flag is <tt>true</tt>, then the arguments of the
+     *        {@link MethodVisitor#visitMaxs visitMaxs} method of the
+     *        {@link MethodVisitor} returned by the
+     *        {@link #visitMethod visitMethod} method will be ignored, and
+     *        computed automatically from the signature and the bytecode of each
+     *        method.
+     */
+    public ClassWriter(final boolean computeMaxs) {
+        this( computeMaxs,
+              false );
+    }
+
+    /**
+     * Constructs a new {@link ClassWriter} object.
+     * 
+     * @param computeMaxs <tt>true</tt> if the maximum stack size and the
+     *        maximum number of local variables must be automatically computed.
+     *        If this flag is <tt>true</tt>, then the arguments of the
+     *        {@link MethodVisitor#visitMaxs visitMaxs} method of the
+     *        {@link MethodVisitor} returned by the
+     *        {@link #visitMethod visitMethod} method will be ignored, and
+     *        computed automatically from the signature and the bytecode of each
+     *        method.
+     * @param skipUnknownAttributes <b>Deprecated</b>. The value of this
+     *        parameter is ignored.
+     */
+    public ClassWriter(final boolean computeMaxs,
+                       final boolean skipUnknownAttributes) {
+        this.index = 1;
+        this.pool = new ByteVector();
+        this.items = new Item[256];
+        this.threshold = (int) (0.75d * this.items.length);
+        this.key = new Item();
+        this.key2 = new Item();
+        this.key3 = new Item();
+        this.computeMaxs = computeMaxs;
+    }
+
+    /**
+     * Constructs a new {@link ClassWriter} object and enables optimizations for
+     * "mostly add" bytecode transformations. These optimizations are the
+     * following:
+     * 
+     * <ul> <li>The constant pool from the original class is copied as is in
+     * the new class, which saves time. New constant pool entries will be added
+     * at the end if necessary, but unused constant pool entries <i>won't be
+     * removed</i>.</li> <li>Methods that are not transformed are copied as
+     * is in the new class, directly from the original class bytecode (i.e.
+     * without emitting visit events for all the method instructions), which
+     * saves a <i>lot</i> of time. Untransformed methods are detected by the
+     * fact that the {@link ClassReader} receives {@link MethodVisitor} objects
+     * that come from a {@link ClassWriter} (and not from a custom
+     * {@link ClassAdapter} or any other {@link ClassVisitor} instance).</li>
+     * </ul>
+     * 
+     * @param classReader the {@link ClassReader} used to read the original
+     *        class. It will be used to copy the entire constant pool from the
+     *        original class and also to copy other fragments of original
+     *        bytecode where applicable.
+     * @param computeMaxs <tt>true</tt> if the maximum stack size and the
+     *        maximum number of local variables must be automatically computed.
+     *        If this flag is <tt>true</tt>, then the arguments of the
+     *        {@link MethodVisitor#visitMaxs visitMaxs} method of the
+     *        {@link MethodVisitor} returned by the
+     *        {@link #visitMethod visitMethod} method will be ignored, and
+     *        computed automatically from the signature and the bytecode of each
+     *        method.
+     */
+    public ClassWriter(final ClassReader classReader,
+                       final boolean computeMaxs) {
+        this( computeMaxs,
+              false );
+        classReader.copyPool( this );
+        this.cr = classReader;
+    }
+
+    // ------------------------------------------------------------------------
+    // Implementation of the ClassVisitor interface
+    // ------------------------------------------------------------------------
+
+    public void visit(final int version,
+                      final int access,
+                      final String name,
+                      final String signature,
+                      final String superName,
+                      final String[] interfaces) {
+        this.version = version;
+        this.access = access;
+        this.name = newClass( name );
+        if ( signature != null ) {
+            this.signature = newUTF8( signature );
+        }
+        this.superName = superName == null ? 0 : newClass( superName );
+        if ( interfaces != null && interfaces.length > 0 ) {
+            this.interfaceCount = interfaces.length;
+            this.interfaces = new int[this.interfaceCount];
+            for ( int i = 0; i < this.interfaceCount; ++i ) {
+                this.interfaces[i] = newClass( interfaces[i] );
+            }
+        }
+    }
+
+    public void visitSource(final String file,
+                            final String debug) {
+        if ( file != null ) {
+            this.sourceFile = newUTF8( file );
+        }
+        if ( debug != null ) {
+            this.sourceDebug = new ByteVector().putUTF8( debug );
+        }
+    }
+
+    public void visitOuterClass(final String owner,
+                                final String name,
+                                final String desc) {
+        this.enclosingMethodOwner = newClass( owner );
+        if ( name != null && desc != null ) {
+            this.enclosingMethod = newNameType( name,
+                                                desc );
+        }
+    }
+
+    public AnnotationVisitor visitAnnotation(final String desc,
+                                             final boolean visible) {
+        final ByteVector bv = new ByteVector();
+        // write type, and reserve space for values count
+        bv.putShort( newUTF8( desc ) ).putShort( 0 );
+        final AnnotationWriter aw = new AnnotationWriter( this,
+                                                          true,
+                                                          bv,
+                                                          bv,
+                                                          2 );
+        if ( visible ) {
+            aw.next = this.anns;
+            this.anns = aw;
+        } else {
+            aw.next = this.ianns;
+            this.ianns = aw;
+        }
+        return aw;
+    }
+
+    public void visitAttribute(final Attribute attr) {
+        attr.next = this.attrs;
+        this.attrs = attr;
+    }
+
+    public void visitInnerClass(final String name,
+                                final String outerName,
+                                final String innerName,
+                                final int access) {
+        if ( this.innerClasses == null ) {
+            this.innerClasses = new ByteVector();
+        }
+        ++this.innerClassesCount;
+        this.innerClasses.putShort( name == null ? 0 : newClass( name ) );
+        this.innerClasses.putShort( outerName == null ? 0 : newClass( outerName ) );
+        this.innerClasses.putShort( innerName == null ? 0 : newUTF8( innerName ) );
+        this.innerClasses.putShort( access );
+    }
+
+    public FieldVisitor visitField(final int access,
+                                   final String name,
+                                   final String desc,
+                                   final String signature,
+                                   final Object value) {
+        return new FieldWriter( this,
+                                access,
+                                name,
+                                desc,
+                                signature,
+                                value );
+    }
+
+    public MethodVisitor visitMethod(final int access,
+                                     final String name,
+                                     final String desc,
+                                     final String signature,
+                                     final String[] exceptions) {
+        return new MethodWriter( this,
+                                 access,
+                                 name,
+                                 desc,
+                                 signature,
+                                 exceptions,
+                                 this.computeMaxs );
+    }
+
+    public void visitEnd() {
+    }
+
+    // ------------------------------------------------------------------------
+    // Other public methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns the bytecode of the class that was build with this class writer.
+     * 
+     * @return the bytecode of the class that was build with this class writer.
+     */
+    public byte[] toByteArray() {
+        // computes the real size of the bytecode of this class
+        int size = 24 + 2 * this.interfaceCount;
+        int nbFields = 0;
+        FieldWriter fb = this.firstField;
+        while ( fb != null ) {
+            ++nbFields;
+            size += fb.getSize();
+            fb = fb.next;
+        }
+        int nbMethods = 0;
+        MethodWriter mb = this.firstMethod;
+        while ( mb != null ) {
+            ++nbMethods;
+            size += mb.getSize();
+            mb = mb.next;
+        }
+        int attributeCount = 0;
+        if ( this.signature != 0 ) {
+            ++attributeCount;
+            size += 8;
+            newUTF8( "Signature" );
+        }
+        if ( this.sourceFile != 0 ) {
+            ++attributeCount;
+            size += 8;
+            newUTF8( "SourceFile" );
+        }
+        if ( this.sourceDebug != null ) {
+            ++attributeCount;
+            size += this.sourceDebug.length + 4;
+            newUTF8( "SourceDebugExtension" );
+        }
+        if ( this.enclosingMethodOwner != 0 ) {
+            ++attributeCount;
+            size += 10;
+            newUTF8( "EnclosingMethod" );
+        }
+        if ( (this.access & Opcodes.ACC_DEPRECATED) != 0 ) {
+            ++attributeCount;
+            size += 6;
+            newUTF8( "Deprecated" );
+        }
+        if ( (this.access & Opcodes.ACC_SYNTHETIC) != 0 && (this.version & 0xffff) < Opcodes.V1_5 ) {
+            ++attributeCount;
+            size += 6;
+            newUTF8( "Synthetic" );
+        }
+        if ( this.version == Opcodes.V1_4 ) {
+            if ( (this.access & Opcodes.ACC_ANNOTATION) != 0 ) {
+                ++attributeCount;
+                size += 6;
+                newUTF8( "Annotation" );
+            }
+            if ( (this.access & Opcodes.ACC_ENUM) != 0 ) {
+                ++attributeCount;
+                size += 6;
+                newUTF8( "Enum" );
+            }
+        }
+        if ( this.innerClasses != null ) {
+            ++attributeCount;
+            size += 8 + this.innerClasses.length;
+            newUTF8( "InnerClasses" );
+        }
+        if ( this.anns != null ) {
+            ++attributeCount;
+            size += 8 + this.anns.getSize();
+            newUTF8( "RuntimeVisibleAnnotations" );
+        }
+        if ( this.ianns != null ) {
+            ++attributeCount;
+            size += 8 + this.ianns.getSize();
+            newUTF8( "RuntimeInvisibleAnnotations" );
+        }
+        if ( this.attrs != null ) {
+            attributeCount += this.attrs.getCount();
+            size += this.attrs.getSize( this,
+                                        null,
+                                        0,
+                                        -1,
+                                        -1 );
+        }
+        size += this.pool.length;
+        // allocates a byte vector of this size, in order to avoid unnecessary
+        // arraycopy operations in the ByteVector.enlarge() method
+        final ByteVector out = new ByteVector( size );
+        out.putInt( 0xCAFEBABE ).putInt( this.version );
+        out.putShort( this.index ).putByteArray( this.pool.data,
+                                                 0,
+                                                 this.pool.length );
+        out.putShort( this.access ).putShort( this.name ).putShort( this.superName );
+        out.putShort( this.interfaceCount );
+        for ( int i = 0; i < this.interfaceCount; ++i ) {
+            out.putShort( this.interfaces[i] );
+        }
+        out.putShort( nbFields );
+        fb = this.firstField;
+        while ( fb != null ) {
+            fb.put( out );
+            fb = fb.next;
+        }
+        out.putShort( nbMethods );
+        mb = this.firstMethod;
+        while ( mb != null ) {
+            mb.put( out );
+            mb = mb.next;
+        }
+        out.putShort( attributeCount );
+        if ( this.signature != 0 ) {
+            out.putShort( newUTF8( "Signature" ) ).putInt( 2 ).putShort( this.signature );
+        }
+        if ( this.sourceFile != 0 ) {
+            out.putShort( newUTF8( "SourceFile" ) ).putInt( 2 ).putShort( this.sourceFile );
+        }
+        if ( this.sourceDebug != null ) {
+            final int len = this.sourceDebug.length - 2;
+            out.putShort( newUTF8( "SourceDebugExtension" ) ).putInt( len );
+            out.putByteArray( this.sourceDebug.data,
+                              2,
+                              len );
+        }
+        if ( this.enclosingMethodOwner != 0 ) {
+            out.putShort( newUTF8( "EnclosingMethod" ) ).putInt( 4 );
+            out.putShort( this.enclosingMethodOwner ).putShort( this.enclosingMethod );
+        }
+        if ( (this.access & Opcodes.ACC_DEPRECATED) != 0 ) {
+            out.putShort( newUTF8( "Deprecated" ) ).putInt( 0 );
+        }
+        if ( (this.access & Opcodes.ACC_SYNTHETIC) != 0 && (this.version & 0xffff) < Opcodes.V1_5 ) {
+            out.putShort( newUTF8( "Synthetic" ) ).putInt( 0 );
+        }
+        if ( this.version == Opcodes.V1_4 ) {
+            if ( (this.access & Opcodes.ACC_ANNOTATION) != 0 ) {
+                out.putShort( newUTF8( "Annotation" ) ).putInt( 0 );
+            }
+            if ( (this.access & Opcodes.ACC_ENUM) != 0 ) {
+                out.putShort( newUTF8( "Enum" ) ).putInt( 0 );
+            }
+        }
+        if ( this.innerClasses != null ) {
+            out.putShort( newUTF8( "InnerClasses" ) );
+            out.putInt( this.innerClasses.length + 2 ).putShort( this.innerClassesCount );
+            out.putByteArray( this.innerClasses.data,
+                              0,
+                              this.innerClasses.length );
+        }
+        if ( this.anns != null ) {
+            out.putShort( newUTF8( "RuntimeVisibleAnnotations" ) );
+            this.anns.put( out );
+        }
+        if ( this.ianns != null ) {
+            out.putShort( newUTF8( "RuntimeInvisibleAnnotations" ) );
+            this.ianns.put( out );
+        }
+        if ( this.attrs != null ) {
+            this.attrs.put( this,
+                            null,
+                            0,
+                            -1,
+                            -1,
+                            out );
+        }
+        return out.data;
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods: constant pool management
+    // ------------------------------------------------------------------------
+
+    /**
+     * Adds a number or string constant to the constant pool of the class being
+     * build. Does nothing if the constant pool already contains a similar item.
+     * 
+     * @param cst the value of the constant to be added to the constant pool.
+     *        This parameter must be an {@link Integer}, a {@link Float}, a
+     *        {@link Long}, a {@link Double}, a {@link String} or a
+     *        {@link Type}.
+     * @return a new or already existing constant item with the given value.
+     */
+    Item newConstItem(final Object cst) {
+        if ( cst instanceof Integer ) {
+            final int val = ((Integer) cst).intValue();
+            return newInteger( val );
+        } else if ( cst instanceof Byte ) {
+            final int val = ((Byte) cst).intValue();
+            return newInteger( val );
+        } else if ( cst instanceof Character ) {
+            final int val = ((Character) cst).charValue();
+            return newInteger( val );
+        } else if ( cst instanceof Short ) {
+            final int val = ((Short) cst).intValue();
+            return newInteger( val );
+        } else if ( cst instanceof Boolean ) {
+            final int val = ((Boolean) cst).booleanValue() ? 1 : 0;
+            return newInteger( val );
+        } else if ( cst instanceof Float ) {
+            final float val = ((Float) cst).floatValue();
+            return newFloat( val );
+        } else if ( cst instanceof Long ) {
+            final long val = ((Long) cst).longValue();
+            return newLong( val );
+        } else if ( cst instanceof Double ) {
+            final double val = ((Double) cst).doubleValue();
+            return newDouble( val );
+        } else if ( cst instanceof String ) {
+            return newString( (String) cst );
+        } else if ( cst instanceof Type ) {
+            final Type t = (Type) cst;
+            return newClassItem( t.getSort() == Type.OBJECT ? t.getInternalName() : t.getDescriptor() );
+        } else {
+            throw new IllegalArgumentException( "value " + cst );
+        }
+    }
+
+    /**
+     * Adds a number or string constant to the constant pool of the class being
+     * build. Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     * 
+     * @param cst the value of the constant to be added to the constant pool.
+     *        This parameter must be an {@link Integer}, a {@link Float}, a
+     *        {@link Long}, a {@link Double} or a {@link String}.
+     * @return the index of a new or already existing constant item with the
+     *         given value.
+     */
+    public int newConst(final Object cst) {
+        return newConstItem( cst ).index;
+    }
+
+    /**
+     * Adds an UTF8 string to the constant pool of the class being build. Does
+     * nothing if the constant pool already contains a similar item. <i>This
+     * method is intended for {@link Attribute} sub classes, and is normally not
+     * needed by class generators or adapters.</i>
+     * 
+     * @param value the String value.
+     * @return the index of a new or already existing UTF8 item.
+     */
+    public int newUTF8(final String value) {
+        this.key.set( ClassWriter.UTF8,
+                      value,
+                      null,
+                      null );
+        Item result = get( this.key );
+        if ( result == null ) {
+            this.pool.putByte( ClassWriter.UTF8 ).putUTF8( value );
+            result = new Item( this.index++,
+                               this.key );
+            put( result );
+        }
+        return result.index;
+    }
+
+    /**
+     * Adds a class reference to the constant pool of the class being build.
+     * Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     * 
+     * @param value the internal name of the class.
+     * @return the index of a new or already existing class reference item.
+     */
+    public int newClass(final String value) {
+        return newClassItem( value ).index;
+    }
+
+    /**
+     * Adds a class reference to the constant pool of the class being build.
+     * Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     * 
+     * @param value the internal name of the class.
+     * @return a new or already existing class reference item.
+     */
+    private Item newClassItem(final String value) {
+        this.key2.set( ClassWriter.CLASS,
+                       value,
+                       null,
+                       null );
+        Item result = get( this.key2 );
+        if ( result == null ) {
+            this.pool.put12( ClassWriter.CLASS,
+                             newUTF8( value ) );
+            result = new Item( this.index++,
+                               this.key2 );
+            put( result );
+        }
+        return result;
+    }
+
+    /**
+     * Adds a field reference to the constant pool of the class being build.
+     * Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     * 
+     * @param owner the internal name of the field's owner class.
+     * @param name the field's name.
+     * @param desc the field's descriptor.
+     * @return the index of a new or already existing field reference item.
+     */
+    public int newField(final String owner,
+                        final String name,
+                        final String desc) {
+        this.key3.set( ClassWriter.FIELD,
+                       owner,
+                       name,
+                       desc );
+        Item result = get( this.key3 );
+        if ( result == null ) {
+            put122( ClassWriter.FIELD,
+                    newClass( owner ),
+                    newNameType( name,
+                                 desc ) );
+            result = new Item( this.index++,
+                               this.key3 );
+            put( result );
+        }
+        return result.index;
+    }
+
+    /**
+     * Adds a method reference to the constant pool of the class being build.
+     * Does nothing if the constant pool already contains a similar item.
+     * 
+     * @param owner the internal name of the method's owner class.
+     * @param name the method's name.
+     * @param desc the method's descriptor.
+     * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
+     * @return a new or already existing method reference item.
+     */
+    Item newMethodItem(final String owner,
+                       final String name,
+                       final String desc,
+                       final boolean itf) {
+        final int type = itf ? ClassWriter.IMETH : ClassWriter.METH;
+        this.key3.set( type,
+                       owner,
+                       name,
+                       desc );
+        Item result = get( this.key3 );
+        if ( result == null ) {
+            put122( type,
+                    newClass( owner ),
+                    newNameType( name,
+                                 desc ) );
+            result = new Item( this.index++,
+                               this.key3 );
+            put( result );
+        }
+        return result;
+    }
+
+    /**
+     * Adds a method reference to the constant pool of the class being build.
+     * Does nothing if the constant pool already contains a similar item.
+     * <i>This method is intended for {@link Attribute} sub classes, and is
+     * normally not needed by class generators or adapters.</i>
+     * 
+     * @param owner the internal name of the method's owner class.
+     * @param name the method's name.
+     * @param desc the method's descriptor.
+     * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
+     * @return the index of a new or already existing method reference item.
+     */
+    public int newMethod(final String owner,
+                         final String name,
+                         final String desc,
+                         final boolean itf) {
+        return newMethodItem( owner,
+                              name,
+                              desc,
+                              itf ).index;
+    }
+
+    /**
+     * Adds an integer to the constant pool of the class being build. Does
+     * nothing if the constant pool already contains a similar item.
+     * 
+     * @param value the int value.
+     * @return a new or already existing int item.
+     */
+    Item newInteger(final int value) {
+        this.key.set( value );
+        Item result = get( this.key );
+        if ( result == null ) {
+            this.pool.putByte( ClassWriter.INT ).putInt( value );
+            result = new Item( this.index++,
+                               this.key );
+            put( result );
+        }
+        return result;
+    }
+
+    /**
+     * Adds a float to the constant pool of the class being build. Does nothing
+     * if the constant pool already contains a similar item.
+     * 
+     * @param value the float value.
+     * @return a new or already existing float item.
+     */
+    Item newFloat(final float value) {
+        this.key.set( value );
+        Item result = get( this.key );
+        if ( result == null ) {
+            this.pool.putByte( ClassWriter.FLOAT ).putInt( Float.floatToIntBits( value ) );
+            result = new Item( this.index++,
+                               this.key );
+            put( result );
+        }
+        return result;
+    }
+
+    /**
+     * Adds a long to the constant pool of the class being build. Does nothing
+     * if the constant pool already contains a similar item.
+     * 
+     * @param value the long value.
+     * @return a new or already existing long item.
+     */
+    Item newLong(final long value) {
+        this.key.set( value );
+        Item result = get( this.key );
+        if ( result == null ) {
+            this.pool.putByte( ClassWriter.LONG ).putLong( value );
+            result = new Item( this.index,
+                               this.key );
+            put( result );
+            this.index += 2;
+        }
+        return result;
+    }
+
+    /**
+     * Adds a double to the constant pool of the class being build. Does nothing
+     * if the constant pool already contains a similar item.
+     * 
+     * @param value the double value.
+     * @return a new or already existing double item.
+     */
+    Item newDouble(final double value) {
+        this.key.set( value );
+        Item result = get( this.key );
+        if ( result == null ) {
+            this.pool.putByte( ClassWriter.DOUBLE ).putLong( Double.doubleToLongBits( value ) );
+            result = new Item( this.index,
+                               this.key );
+            put( result );
+            this.index += 2;
+        }
+        return result;
+    }
+
+    /**
+     * Adds a string to the constant pool of the class being build. Does nothing
+     * if the constant pool already contains a similar item.
+     * 
+     * @param value the String value.
+     * @return a new or already existing string item.
+     */
+    private Item newString(final String value) {
+        this.key2.set( ClassWriter.STR,
+                       value,
+                       null,
+                       null );
+        Item result = get( this.key2 );
+        if ( result == null ) {
+            this.pool.put12( ClassWriter.STR,
+                             newUTF8( value ) );
+            result = new Item( this.index++,
+                               this.key2 );
+            put( result );
+        }
+        return result;
+    }
+
+    /**
+     * Adds a name and type to the constant pool of the class being build. Does
+     * nothing if the constant pool already contains a similar item. <i>This
+     * method is intended for {@link Attribute} sub classes, and is normally not
+     * needed by class generators or adapters.</i>
+     * 
+     * @param name a name.
+     * @param desc a type descriptor.
+     * @return the index of a new or already existing name and type item.
+     */
+    public int newNameType(final String name,
+                           final String desc) {
+        this.key2.set( ClassWriter.NAME_TYPE,
+                       name,
+                       desc,
+                       null );
+        Item result = get( this.key2 );
+        if ( result == null ) {
+            put122( ClassWriter.NAME_TYPE,
+                    newUTF8( name ),
+                    newUTF8( desc ) );
+            result = new Item( this.index++,
+                               this.key2 );
+            put( result );
+        }
+        return result.index;
+    }
+
+    /**
+     * Returns the constant pool's hash table item which is equal to the given
+     * item.
+     * 
+     * @param key a constant pool item.
+     * @return the constant pool's hash table item which is equal to the given
+     *         item, or <tt>null</tt> if there is no such item.
+     */
+    private Item get(final Item key) {
+        Item i = this.items[key.hashCode % this.items.length];
+        while ( i != null && !key.isEqualTo( i ) ) {
+            i = i.next;
+        }
+        return i;
+    }
+
+    /**
+     * Puts the given item in the constant pool's hash table. The hash table
+     * <i>must</i> not already contains this item.
+     * 
+     * @param i the item to be added to the constant pool's hash table.
+     */
+    private void put(final Item i) {
+        if ( this.index > this.threshold ) {
+            final int ll = this.items.length;
+            final int nl = ll * 2 + 1;
+            final Item[] newItems = new Item[nl];
+            for ( int l = ll - 1; l >= 0; --l ) {
+                Item j = this.items[l];
+                while ( j != null ) {
+                    final int index = j.hashCode % newItems.length;
+                    final Item k = j.next;
+                    j.next = newItems[index];
+                    newItems[index] = j;
+                    j = k;
+                }
+            }
+            this.items = newItems;
+            this.threshold = (int) (nl * 0.75);
+        }
+        final int index = i.hashCode % this.items.length;
+        i.next = this.items[index];
+        this.items[index] = i;
+    }
+
+    /**
+     * Puts one byte and two shorts into the constant pool.
+     * 
+     * @param b a byte.
+     * @param s1 a short.
+     * @param s2 another short.
+     */
+    private void put122(final int b,
+                        final int s1,
+                        final int s2) {
+        this.pool.put12( b,
+                         s1 ).putShort( s2 );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Edge.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Edge.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Edge.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,57 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm;
+
+/**
+ * An edge in the control flow graph of a method body. See {@link Label Label}.
+ * 
+ * @author Eric Bruneton
+ */
+class Edge {
+
+    /**
+     * The (relative) stack size in the basic block from which this edge
+     * originates. This size is equal to the stack size at the "jump"
+     * instruction to which this edge corresponds, relatively to the stack size
+     * at the beginning of the originating basic block.
+     */
+    int   stackSize;
+
+    /**
+     * The successor block of the basic block from which this edge originates.
+     */
+    Label successor;
+
+    /**
+     * The next edge in the list of successors of the originating basic block.
+     * See {@link Label#successors successors}.
+     */
+    Edge  next;
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/FieldVisitor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/FieldVisitor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/FieldVisitor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,64 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm;
+
+/**
+ * A visitor to visit a Java field. The methods of this interface must be called
+ * in the following order: ( <tt>visitAnnotation</tt> |
+ * <tt>visitAttribute</tt> )* <tt>visitEnd</tt>.
+ * 
+ * @author Eric Bruneton
+ */
+public interface FieldVisitor {
+
+    /**
+     * Visits an annotation of the field.
+     * 
+     * @param desc the class descriptor of the annotation class.
+     * @param visible <tt>true</tt> if the annotation is visible at runtime.
+     * @return a non null visitor to visit the annotation values.
+     */
+    AnnotationVisitor visitAnnotation(String desc,
+                                      boolean visible);
+
+    /**
+     * Visits a non standard attribute of the field.
+     * 
+     * @param attr an attribute.
+     */
+    void visitAttribute(Attribute attr);
+
+    /**
+     * Visits the end of the field. This method, which is the last one to be
+     * called, is used to inform the visitor that all the annotations and
+     * attributes of the field have been visited.
+     */
+    void visitEnd();
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/FieldWriter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/FieldWriter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/FieldWriter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,281 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm;
+
+/**
+ * An {@link FieldVisitor} that generates Java fields in bytecode form.
+ * 
+ * @author Eric Bruneton
+ */
+final class FieldWriter
+    implements
+    FieldVisitor {
+
+    /**
+     * Next field writer (see {@link ClassWriter#firstField firstField}).
+     */
+    FieldWriter              next;
+
+    /**
+     * The class writer to which this field must be added.
+     */
+    private ClassWriter      cw;
+
+    /**
+     * Access flags of this field.
+     */
+    private int              access;
+
+    /**
+     * The index of the constant pool item that contains the name of this
+     * method.
+     */
+    private int              name;
+
+    /**
+     * The index of the constant pool item that contains the descriptor of this
+     * field.
+     */
+    private int              desc;
+
+    /**
+     * The index of the constant pool item that contains the signature of this
+     * field.
+     */
+    private int              signature;
+
+    /**
+     * The index of the constant pool item that contains the constant value of
+     * this field.
+     */
+    private int              value;
+
+    /**
+     * The runtime visible annotations of this field. May be <tt>null</tt>.
+     */
+    private AnnotationWriter anns;
+
+    /**
+     * The runtime invisible annotations of this field. May be <tt>null</tt>.
+     */
+    private AnnotationWriter ianns;
+
+    /**
+     * The non standard attributes of this field. May be <tt>null</tt>.
+     */
+    private Attribute        attrs;
+
+    // ------------------------------------------------------------------------
+    // Constructor
+    // ------------------------------------------------------------------------
+
+    /**
+     * Constructs a new {@link FieldWriter}.
+     * 
+     * @param cw the class writer to which this field must be added.
+     * @param access the field's access flags (see {@link Opcodes}).
+     * @param name the field's name.
+     * @param desc the field's descriptor (see {@link Type}).
+     * @param signature the field's signature. May be <tt>null</tt>.
+     * @param value the field's constant value. May be <tt>null</tt>.
+     */
+    protected FieldWriter(final ClassWriter cw,
+                          final int access,
+                          final String name,
+                          final String desc,
+                          final String signature,
+                          final Object value) {
+        if ( cw.firstField == null ) {
+            cw.firstField = this;
+        } else {
+            cw.lastField.next = this;
+        }
+        cw.lastField = this;
+        this.cw = cw;
+        this.access = access;
+        this.name = cw.newUTF8( name );
+        this.desc = cw.newUTF8( desc );
+        if ( signature != null ) {
+            this.signature = cw.newUTF8( signature );
+        }
+        if ( value != null ) {
+            this.value = cw.newConstItem( value ).index;
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Implementation of the FieldVisitor interface
+    // ------------------------------------------------------------------------
+
+    public AnnotationVisitor visitAnnotation(final String desc,
+                                             final boolean visible) {
+        final ByteVector bv = new ByteVector();
+        // write type, and reserve space for values count
+        bv.putShort( this.cw.newUTF8( desc ) ).putShort( 0 );
+        final AnnotationWriter aw = new AnnotationWriter( this.cw,
+                                                          true,
+                                                          bv,
+                                                          bv,
+                                                          2 );
+        if ( visible ) {
+            aw.next = this.anns;
+            this.anns = aw;
+        } else {
+            aw.next = this.ianns;
+            this.ianns = aw;
+        }
+        return aw;
+    }
+
+    public void visitAttribute(final Attribute attr) {
+        attr.next = this.attrs;
+        this.attrs = attr;
+    }
+
+    public void visitEnd() {
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns the size of this field.
+     * 
+     * @return the size of this field.
+     */
+    int getSize() {
+        int size = 8;
+        if ( this.value != 0 ) {
+            this.cw.newUTF8( "ConstantValue" );
+            size += 8;
+        }
+        if ( (this.access & Opcodes.ACC_SYNTHETIC) != 0 && (this.cw.version & 0xffff) < Opcodes.V1_5 ) {
+            this.cw.newUTF8( "Synthetic" );
+            size += 6;
+        }
+        if ( (this.access & Opcodes.ACC_DEPRECATED) != 0 ) {
+            this.cw.newUTF8( "Deprecated" );
+            size += 6;
+        }
+        if ( this.cw.version == Opcodes.V1_4 && (this.access & Opcodes.ACC_ENUM) != 0 ) {
+            this.cw.newUTF8( "Enum" );
+            size += 6;
+        }
+        if ( this.signature != 0 ) {
+            this.cw.newUTF8( "Signature" );
+            size += 8;
+        }
+        if ( this.anns != null ) {
+            this.cw.newUTF8( "RuntimeVisibleAnnotations" );
+            size += 8 + this.anns.getSize();
+        }
+        if ( this.ianns != null ) {
+            this.cw.newUTF8( "RuntimeInvisibleAnnotations" );
+            size += 8 + this.ianns.getSize();
+        }
+        if ( this.attrs != null ) {
+            size += this.attrs.getSize( this.cw,
+                                        null,
+                                        0,
+                                        -1,
+                                        -1 );
+        }
+        return size;
+    }
+
+    /**
+     * Puts the content of this field into the given byte vector.
+     * 
+     * @param out where the content of this field must be put.
+     */
+    void put(final ByteVector out) {
+        out.putShort( this.access ).putShort( this.name ).putShort( this.desc );
+        int attributeCount = 0;
+        if ( this.value != 0 ) {
+            ++attributeCount;
+        }
+        if ( (this.access & Opcodes.ACC_SYNTHETIC) != 0 && (this.cw.version & 0xffff) < Opcodes.V1_5 ) {
+            ++attributeCount;
+        }
+        if ( (this.access & Opcodes.ACC_DEPRECATED) != 0 ) {
+            ++attributeCount;
+        }
+        if ( this.cw.version == Opcodes.V1_4 && (this.access & Opcodes.ACC_ENUM) != 0 ) {
+            ++attributeCount;
+        }
+        if ( this.signature != 0 ) {
+            ++attributeCount;
+        }
+        if ( this.anns != null ) {
+            ++attributeCount;
+        }
+        if ( this.ianns != null ) {
+            ++attributeCount;
+        }
+        if ( this.attrs != null ) {
+            attributeCount += this.attrs.getCount();
+        }
+        out.putShort( attributeCount );
+        if ( this.value != 0 ) {
+            out.putShort( this.cw.newUTF8( "ConstantValue" ) );
+            out.putInt( 2 ).putShort( this.value );
+        }
+        if ( (this.access & Opcodes.ACC_SYNTHETIC) != 0 && (this.cw.version & 0xffff) < Opcodes.V1_5 ) {
+            out.putShort( this.cw.newUTF8( "Synthetic" ) ).putInt( 0 );
+        }
+        if ( (this.access & Opcodes.ACC_DEPRECATED) != 0 ) {
+            out.putShort( this.cw.newUTF8( "Deprecated" ) ).putInt( 0 );
+        }
+        if ( this.cw.version == Opcodes.V1_4 && (this.access & Opcodes.ACC_ENUM) != 0 ) {
+            out.putShort( this.cw.newUTF8( "Enum" ) ).putInt( 0 );
+        }
+        if ( this.signature != 0 ) {
+            out.putShort( this.cw.newUTF8( "Signature" ) );
+            out.putInt( 2 ).putShort( this.signature );
+        }
+        if ( this.anns != null ) {
+            out.putShort( this.cw.newUTF8( "RuntimeVisibleAnnotations" ) );
+            this.anns.put( out );
+        }
+        if ( this.ianns != null ) {
+            out.putShort( this.cw.newUTF8( "RuntimeInvisibleAnnotations" ) );
+            this.ianns.put( out );
+        }
+        if ( this.attrs != null ) {
+            this.attrs.put( this.cw,
+                            null,
+                            0,
+                            -1,
+                            -1,
+                            out );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Handler.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Handler.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Handler.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,70 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm;
+
+/**
+ * Information about an exception handler block.
+ * 
+ * @author Eric Bruneton
+ */
+class Handler {
+
+    /**
+     * Beginning of the exception handler's scope (inclusive).
+     */
+    Label   start;
+
+    /**
+     * End of the exception handler's scope (exclusive).
+     */
+    Label   end;
+
+    /**
+     * Beginning of the exception handler's code.
+     */
+    Label   handler;
+
+    /**
+     * Internal name of the type of exceptions handled by this handler, or
+     * <tt>null</tt> to catch any exceptions.
+     */
+    String  desc;
+
+    /**
+     * Constant pool index of the internal name of the type of exceptions
+     * handled by this handler, or 0 to catch any exceptions.
+     */
+    int     type;
+
+    /**
+     * Next exception handler block info.
+     */
+    Handler next;
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Item.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Item.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Item.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,246 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm;
+
+/**
+ * A constant pool item. Constant pool items can be created with the 'newXXX'
+ * methods in the {@link ClassWriter} class.
+ * 
+ * @author Eric Bruneton
+ */
+final class Item {
+
+    /**
+     * Index of this item in the constant pool.
+     */
+    int    index;
+
+    /**
+     * Type of this constant pool item. A single class is used to represent all
+     * constant pool item types, in order to minimize the bytecode size of this
+     * package. The value of this field is one of {@link ClassWriter#INT},
+     * {@link ClassWriter#LONG}, {@link ClassWriter#FLOAT},
+     * {@link ClassWriter#DOUBLE}, {@link ClassWriter#UTF8},
+     * {@link ClassWriter#STR}, {@link ClassWriter#CLASS},
+     * {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
+     * {@link ClassWriter#METH}, {@link ClassWriter#IMETH}.
+     */
+    int    type;
+
+    /**
+     * Value of this item, for an integer item.
+     */
+    int    intVal;
+
+    /**
+     * Value of this item, for a long item.
+     */
+    long   longVal;
+
+    /**
+     * Value of this item, for a float item.
+     */
+    float  floatVal;
+
+    /**
+     * Value of this item, for a double item.
+     */
+    double doubleVal;
+
+    /**
+     * First part of the value of this item, for items that do not hold a
+     * primitive value.
+     */
+    String strVal1;
+
+    /**
+     * Second part of the value of this item, for items that do not hold a
+     * primitive value.
+     */
+    String strVal2;
+
+    /**
+     * Third part of the value of this item, for items that do not hold a
+     * primitive value.
+     */
+    String strVal3;
+
+    /**
+     * The hash code value of this constant pool item.
+     */
+    int    hashCode;
+
+    /**
+     * Link to another constant pool item, used for collision lists in the
+     * constant pool's hash table.
+     */
+    Item   next;
+
+    /**
+     * Constructs an uninitialized {@link Item}.
+     */
+    Item() {
+    }
+
+    Item(final int index) {
+        this.index = index;
+    }
+
+    /**
+     * Constructs a copy of the given item.
+     * 
+     * @param index index of the item to be constructed.
+     * @param i the item that must be copied into the item to be constructed.
+     */
+    Item(final int index,
+         final Item i) {
+        this.index = index;
+        this.type = i.type;
+        this.intVal = i.intVal;
+        this.longVal = i.longVal;
+        this.floatVal = i.floatVal;
+        this.doubleVal = i.doubleVal;
+        this.strVal1 = i.strVal1;
+        this.strVal2 = i.strVal2;
+        this.strVal3 = i.strVal3;
+        this.hashCode = i.hashCode;
+    }
+
+    /**
+     * Sets this item to an integer item.
+     * 
+     * @param intVal the value of this item.
+     */
+    void set(final int intVal) {
+        this.type = ClassWriter.INT;
+        this.intVal = intVal;
+        this.hashCode = 0x7FFFFFFF & (this.type + intVal);
+    }
+
+    /**
+     * Sets this item to a long item.
+     * 
+     * @param longVal the value of this item.
+     */
+    void set(final long longVal) {
+        this.type = ClassWriter.LONG;
+        this.longVal = longVal;
+        this.hashCode = 0x7FFFFFFF & (this.type + (int) longVal);
+    }
+
+    /**
+     * Sets this item to a float item.
+     * 
+     * @param floatVal the value of this item.
+     */
+    void set(final float floatVal) {
+        this.type = ClassWriter.FLOAT;
+        this.floatVal = floatVal;
+        this.hashCode = 0x7FFFFFFF & (this.type + (int) floatVal);
+    }
+
+    /**
+     * Sets this item to a double item.
+     * 
+     * @param doubleVal the value of this item.
+     */
+    void set(final double doubleVal) {
+        this.type = ClassWriter.DOUBLE;
+        this.doubleVal = doubleVal;
+        this.hashCode = 0x7FFFFFFF & (this.type + (int) doubleVal);
+    }
+
+    /**
+     * Sets this item to an item that do not hold a primitive value.
+     * 
+     * @param type the type of this item.
+     * @param strVal1 first part of the value of this item.
+     * @param strVal2 second part of the value of this item.
+     * @param strVal3 third part of the value of this item.
+     */
+    void set(final int type,
+             final String strVal1,
+             final String strVal2,
+             final String strVal3) {
+        this.type = type;
+        this.strVal1 = strVal1;
+        this.strVal2 = strVal2;
+        this.strVal3 = strVal3;
+        switch ( type ) {
+            case ClassWriter.UTF8 :
+            case ClassWriter.STR :
+            case ClassWriter.CLASS :
+                this.hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
+                return;
+            case ClassWriter.NAME_TYPE :
+                this.hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() * strVal2.hashCode());
+                return;
+                // ClassWriter.FIELD:
+                // ClassWriter.METH:
+                // ClassWriter.IMETH:                    
+            default :
+                this.hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() * strVal2.hashCode() * strVal3.hashCode());
+        }
+    }
+
+    /**
+     * Indicates if the given item is equal to this one.
+     * 
+     * @param i the item to be compared to this one.
+     * @return <tt>true</tt> if the given item if equal to this one,
+     *         <tt>false</tt> otherwise.
+     */
+    boolean isEqualTo(final Item i) {
+        if ( i.type == this.type ) {
+            switch ( this.type ) {
+                case ClassWriter.INT :
+                    return i.intVal == this.intVal;
+                case ClassWriter.LONG :
+                    return i.longVal == this.longVal;
+                case ClassWriter.FLOAT :
+                    return i.floatVal == this.floatVal;
+                case ClassWriter.DOUBLE :
+                    return i.doubleVal == this.doubleVal;
+                case ClassWriter.UTF8 :
+                case ClassWriter.STR :
+                case ClassWriter.CLASS :
+                    return i.strVal1.equals( this.strVal1 );
+                case ClassWriter.NAME_TYPE :
+                    return i.strVal1.equals( this.strVal1 ) && i.strVal2.equals( this.strVal2 );
+                    // ClassWriter.FIELD:
+                    // ClassWriter.METH:
+                    // ClassWriter.IMETH:                    
+                default :
+                    return i.strVal1.equals( this.strVal1 ) && i.strVal2.equals( this.strVal2 ) && i.strVal3.equals( this.strVal3 );
+            }
+        }
+        return false;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Label.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Label.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Label.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,295 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm;
+
+/**
+ * A label represents a position in the bytecode of a method. Labels are used
+ * for jump, goto, and switch instructions, and for try catch blocks.
+ * 
+ * @author Eric Bruneton
+ */
+public class Label {
+
+    /**
+     * The line number corresponding to this label, if known.
+     */
+    int           line;
+
+    /**
+     * Indicates if the position of this label is known.
+     */
+    boolean       resolved;
+
+    /**
+     * The position of this label in the code, if known.
+     */
+    int           position;
+
+    /**
+     * If the label position has been updated, after instruction resizing.
+     */
+    boolean       resized;
+
+    /**
+     * Number of forward references to this label, times two.
+     */
+    private int   referenceCount;
+
+    /**
+     * Informations about forward references. Each forward reference is
+     * described by two consecutive integers in this array: the first one is the
+     * position of the first byte of the bytecode instruction that contains the
+     * forward reference, while the second is the position of the first byte of
+     * the forward reference itself. In fact the sign of the first integer
+     * indicates if this reference uses 2 or 4 bytes, and its absolute value
+     * gives the position of the bytecode instruction.
+     */
+    private int[] srcAndRefPositions;
+
+    /*
+     * Fields for the control flow graph analysis algorithm (used to compute the
+     * maximum stack size). A control flow graph contains one node per "basic
+     * block", and one edge per "jump" from one basic block to another. Each
+     * node (i.e., each basic block) is represented by the Label object that
+     * corresponds to the first instruction of this basic block. Each node also
+     * stores the list of it successors in the graph, as a linked list of Edge
+     * objects.
+     */
+
+    /**
+     * The stack size at the beginning of this basic block. This size is
+     * initially unknown. It is computed by the control flow analysis algorithm
+     * (see {@link MethodWriter#visitMaxs visitMaxs}).
+     */
+    int           beginStackSize;
+
+    /**
+     * The (relative) maximum stack size corresponding to this basic block. This
+     * size is relative to the stack size at the beginning of the basic block,
+     * i.e., the true maximum stack size is equal to {@link #beginStackSize
+     * beginStackSize} + {@link #maxStackSize maxStackSize}.
+     */
+    int           maxStackSize;
+
+    /**
+     * The successors of this node in the control flow graph. These successors
+     * are stored in a linked list of {@link Edge Edge} objects, linked to each
+     * other by their {@link Edge#next} field.
+     */
+    Edge          successors;
+
+    /**
+     * The next basic block in the basic block stack. See
+     * {@link MethodWriter#visitMaxs visitMaxs}.
+     */
+    Label         next;
+
+    /**
+     * <tt>true</tt> if this basic block has been pushed in the basic block
+     * stack. See {@link MethodWriter#visitMaxs visitMaxs}.
+     */
+    boolean       pushed;
+
+    // ------------------------------------------------------------------------
+    // Constructor
+    // ------------------------------------------------------------------------
+
+    /**
+     * Constructs a new label.
+     */
+    public Label() {
+    }
+
+    // ------------------------------------------------------------------------
+    // Methods to compute offsets and to manage forward references
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns the offset corresponding to this label. This offset is computed
+     * from the start of the method's bytecode. <i>This method is intended for
+     * {@link Attribute} sub classes, and is normally not needed by class
+     * generators or adapters.</i>
+     * 
+     * @return the offset corresponding to this label.
+     * @throws IllegalStateException if this label is not resolved yet.
+     */
+    public int getOffset() {
+        if ( !this.resolved ) {
+            throw new IllegalStateException( "Label offset position has not been resolved yet" );
+        }
+        return this.position;
+    }
+
+    /**
+     * Puts a reference to this label in the bytecode of a method. If the
+     * position of the label is known, the offset is computed and written
+     * directly. Otherwise, a null offset is written and a new forward reference
+     * is declared for this label.
+     * 
+     * @param owner the code writer that calls this method.
+     * @param out the bytecode of the method.
+     * @param source the position of first byte of the bytecode instruction that
+     *        contains this label.
+     * @param wideOffset <tt>true</tt> if the reference must be stored in 4
+     *        bytes, or <tt>false</tt> if it must be stored with 2 bytes.
+     * @throws IllegalArgumentException if this label has not been created by
+     *         the given code writer.
+     */
+    void put(final MethodWriter owner,
+             final ByteVector out,
+             final int source,
+             final boolean wideOffset) {
+        if ( this.resolved ) {
+            if ( wideOffset ) {
+                out.putInt( this.position - source );
+            } else {
+                out.putShort( this.position - source );
+            }
+        } else {
+            if ( wideOffset ) {
+                addReference( -1 - source,
+                              out.length );
+                out.putInt( -1 );
+            } else {
+                addReference( source,
+                              out.length );
+                out.putShort( -1 );
+            }
+        }
+    }
+
+    /**
+     * Adds a forward reference to this label. This method must be called only
+     * for a true forward reference, i.e. only if this label is not resolved
+     * yet. For backward references, the offset of the reference can be, and
+     * must be, computed and stored directly.
+     * 
+     * @param sourcePosition the position of the referencing instruction. This
+     *        position will be used to compute the offset of this forward
+     *        reference.
+     * @param referencePosition the position where the offset for this forward
+     *        reference must be stored.
+     */
+    private void addReference(final int sourcePosition,
+                              final int referencePosition) {
+        if ( this.srcAndRefPositions == null ) {
+            this.srcAndRefPositions = new int[6];
+        }
+        if ( this.referenceCount >= this.srcAndRefPositions.length ) {
+            final int[] a = new int[this.srcAndRefPositions.length + 6];
+            System.arraycopy( this.srcAndRefPositions,
+                              0,
+                              a,
+                              0,
+                              this.srcAndRefPositions.length );
+            this.srcAndRefPositions = a;
+        }
+        this.srcAndRefPositions[this.referenceCount++] = sourcePosition;
+        this.srcAndRefPositions[this.referenceCount++] = referencePosition;
+    }
+
+    /**
+     * Resolves all forward references to this label. This method must be called
+     * when this label is added to the bytecode of the method, i.e. when its
+     * position becomes known. This method fills in the blanks that where left
+     * in the bytecode by each forward reference previously added to this label.
+     * 
+     * @param owner the code writer that calls this method.
+     * @param position the position of this label in the bytecode.
+     * @param data the bytecode of the method.
+     * @return <tt>true</tt> if a blank that was left for this label was to
+     *         small to store the offset. In such a case the corresponding jump
+     *         instruction is replaced with a pseudo instruction (using unused
+     *         opcodes) using an unsigned two bytes offset. These pseudo
+     *         instructions will need to be replaced with true instructions with
+     *         wider offsets (4 bytes instead of 2). This is done in
+     *         {@link MethodWriter#resizeInstructions}.
+     * @throws IllegalArgumentException if this label has already been resolved,
+     *         or if it has not been created by the given code writer.
+     */
+    boolean resolve(final MethodWriter owner,
+                    final int position,
+                    final byte[] data) {
+        boolean needUpdate = false;
+        this.resolved = true;
+        this.position = position;
+        int i = 0;
+        while ( i < this.referenceCount ) {
+            final int source = this.srcAndRefPositions[i++];
+            int reference = this.srcAndRefPositions[i++];
+            int offset;
+            if ( source >= 0 ) {
+                offset = position - source;
+                if ( offset < Short.MIN_VALUE || offset > Short.MAX_VALUE ) {
+                    /*
+                     * changes the opcode of the jump instruction, in order to
+                     * be able to find it later (see resizeInstructions in
+                     * MethodWriter). These temporary opcodes are similar to
+                     * jump instruction opcodes, except that the 2 bytes offset
+                     * is unsigned (and can therefore represent values from 0 to
+                     * 65535, which is sufficient since the size of a method is
+                     * limited to 65535 bytes).
+                     */
+                    final int opcode = data[reference - 1] & 0xFF;
+                    if ( opcode <= Opcodes.JSR ) {
+                        // changes IFEQ ... JSR to opcodes 202 to 217
+                        data[reference - 1] = (byte) (opcode + 49);
+                    } else {
+                        // changes IFNULL and IFNONNULL to opcodes 218 and 219
+                        data[reference - 1] = (byte) (opcode + 20);
+                    }
+                    needUpdate = true;
+                }
+                data[reference++] = (byte) (offset >>> 8);
+                data[reference] = (byte) offset;
+            } else {
+                offset = position + source + 1;
+                data[reference++] = (byte) (offset >>> 24);
+                data[reference++] = (byte) (offset >>> 16);
+                data[reference++] = (byte) (offset >>> 8);
+                data[reference] = (byte) offset;
+            }
+        }
+        return needUpdate;
+    }
+
+    // ------------------------------------------------------------------------
+    // Overriden Object methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns a string representation of this label.
+     * 
+     * @return a string representation of this label.
+     */
+    public String toString() {
+        return "L" + System.identityHashCode( this );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/MethodAdapter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/MethodAdapter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/MethodAdapter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,209 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm;
+
+/**
+ * An empty {@link MethodVisitor} that delegates to another
+ * {@link MethodVisitor}. This class can be used as a super class to quickly
+ * implement usefull method adapter classes, just by overriding the necessary
+ * methods.
+ * 
+ * @author Eric Bruneton
+ */
+public class MethodAdapter
+    implements
+    MethodVisitor {
+
+    /**
+     * The {@link MethodVisitor} to which this adapter delegates calls.
+     */
+    protected MethodVisitor mv;
+
+    /**
+     * Constructs a new {@link MethodAdapter} object.
+     * 
+     * @param mv the code visitor to which this adapter must delegate calls.
+     */
+    public MethodAdapter(final MethodVisitor mv) {
+        this.mv = mv;
+    }
+
+    public AnnotationVisitor visitAnnotationDefault() {
+        return this.mv.visitAnnotationDefault();
+    }
+
+    public AnnotationVisitor visitAnnotation(final String desc,
+                                             final boolean visible) {
+        return this.mv.visitAnnotation( desc,
+                                        visible );
+    }
+
+    public AnnotationVisitor visitParameterAnnotation(final int parameter,
+                                                      final String desc,
+                                                      final boolean visible) {
+        return this.mv.visitParameterAnnotation( parameter,
+                                                 desc,
+                                                 visible );
+    }
+
+    public void visitAttribute(final Attribute attr) {
+        this.mv.visitAttribute( attr );
+    }
+
+    public void visitCode() {
+        this.mv.visitCode();
+    }
+
+    public void visitInsn(final int opcode) {
+        this.mv.visitInsn( opcode );
+    }
+
+    public void visitIntInsn(final int opcode,
+                             final int operand) {
+        this.mv.visitIntInsn( opcode,
+                              operand );
+    }
+
+    public void visitVarInsn(final int opcode,
+                             final int var) {
+        this.mv.visitVarInsn( opcode,
+                              var );
+    }
+
+    public void visitTypeInsn(final int opcode,
+                              final String desc) {
+        this.mv.visitTypeInsn( opcode,
+                               desc );
+    }
+
+    public void visitFieldInsn(final int opcode,
+                               final String owner,
+                               final String name,
+                               final String desc) {
+        this.mv.visitFieldInsn( opcode,
+                                owner,
+                                name,
+                                desc );
+    }
+
+    public void visitMethodInsn(final int opcode,
+                                final String owner,
+                                final String name,
+                                final String desc) {
+        this.mv.visitMethodInsn( opcode,
+                                 owner,
+                                 name,
+                                 desc );
+    }
+
+    public void visitJumpInsn(final int opcode,
+                              final Label label) {
+        this.mv.visitJumpInsn( opcode,
+                               label );
+    }
+
+    public void visitLabel(final Label label) {
+        this.mv.visitLabel( label );
+    }
+
+    public void visitLdcInsn(final Object cst) {
+        this.mv.visitLdcInsn( cst );
+    }
+
+    public void visitIincInsn(final int var,
+                              final int increment) {
+        this.mv.visitIincInsn( var,
+                               increment );
+    }
+
+    public void visitTableSwitchInsn(final int min,
+                                     final int max,
+                                     final Label dflt,
+                                     final Label labels[]) {
+        this.mv.visitTableSwitchInsn( min,
+                                      max,
+                                      dflt,
+                                      labels );
+    }
+
+    public void visitLookupSwitchInsn(final Label dflt,
+                                      final int keys[],
+                                      final Label labels[]) {
+        this.mv.visitLookupSwitchInsn( dflt,
+                                       keys,
+                                       labels );
+    }
+
+    public void visitMultiANewArrayInsn(final String desc,
+                                        final int dims) {
+        this.mv.visitMultiANewArrayInsn( desc,
+                                         dims );
+    }
+
+    public void visitTryCatchBlock(final Label start,
+                                   final Label end,
+                                   final Label handler,
+                                   final String type) {
+        this.mv.visitTryCatchBlock( start,
+                                    end,
+                                    handler,
+                                    type );
+    }
+
+    public void visitLocalVariable(final String name,
+                                   final String desc,
+                                   final String signature,
+                                   final Label start,
+                                   final Label end,
+                                   final int index) {
+        this.mv.visitLocalVariable( name,
+                                    desc,
+                                    signature,
+                                    start,
+                                    end,
+                                    index );
+    }
+
+    public void visitLineNumber(final int line,
+                                final Label start) {
+        this.mv.visitLineNumber( line,
+                                 start );
+    }
+
+    public void visitMaxs(final int maxStack,
+                          final int maxLocals) {
+        this.mv.visitMaxs( maxStack,
+                           maxLocals );
+    }
+
+    public void visitEnd() {
+        this.mv.visitEnd();
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/MethodVisitor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/MethodVisitor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/MethodVisitor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,355 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm;
+
+/**
+ * A visitor to visit a Java method. The methods of this interface must be
+ * called in the following order: [ <tt>visitAnnotationDefault</tt> ] (
+ * <tt>visitAnnotation</tt> | <tt>visitParameterAnnotation</tt> |
+ * <tt>visitAttribute</tt> )* [ <tt>visitCode</tt> ( <tt>visit</tt><i>X</i>Insn</tt> |
+ * <tt>visitLabel</tt> | <tt>visitTryCatchBlock</tt> | <tt>visitLocalVariable</tt> |
+ * <tt>visitLineNumber</tt>)* <tt>visitMaxs</tt> ] <tt>visitEnd</tt>. In
+ * addition, the <tt>visit</tt><i>X</i>Insn</tt> and <tt>visitLabel</tt>
+ * methods must be called in the sequential order of the bytecode instructions
+ * of the visited code, and the <tt>visitLocalVariable</tt> and <tt>visitLineNumber</tt>
+ * methods must be called <i>after</i> the labels passed as arguments have been
+ * visited.
+ * 
+ * @author Eric Bruneton
+ */
+public interface MethodVisitor {
+
+    // -------------------------------------------------------------------------
+    // Annotations and non standard attributes
+    // -------------------------------------------------------------------------
+
+    /**
+     * Visits the default value of this annotation interface method.
+     * 
+     * @return a non null visitor to the visit the actual default value of this
+     *         annotation interface method. The 'name' parameters passed to the
+     *         methods of this annotation visitor are ignored. Moreover, exacly
+     *         one visit method must be called on this annotation visitor,
+     *         followed by visitEnd.
+     */
+    AnnotationVisitor visitAnnotationDefault();
+
+    /**
+     * Visits an annotation of this method.
+     * 
+     * @param desc the class descriptor of the annotation class.
+     * @param visible <tt>true</tt> if the annotation is visible at runtime.
+     * @return a non null visitor to visit the annotation values.
+     */
+    AnnotationVisitor visitAnnotation(String desc,
+                                      boolean visible);
+
+    /**
+     * Visits an annotation of a parameter this method.
+     * 
+     * @param parameter the parameter index.
+     * @param desc the class descriptor of the annotation class.
+     * @param visible <tt>true</tt> if the annotation is visible at runtime.
+     * @return a non null visitor to visit the annotation values.
+     */
+    AnnotationVisitor visitParameterAnnotation(int parameter,
+                                               String desc,
+                                               boolean visible);
+
+    /**
+     * Visits a non standard attribute of this method.
+     * 
+     * @param attr an attribute.
+     */
+    void visitAttribute(Attribute attr);
+
+    /**
+     * Starts the visit of the method's code, if any (i.e. non abstract method).
+     */
+    void visitCode();
+
+    // -------------------------------------------------------------------------
+    // Normal instructions
+    // -------------------------------------------------------------------------
+
+    /**
+     * Visits a zero operand instruction.
+     * 
+     * @param opcode the opcode of the instruction to be visited. This opcode is
+     *        either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2,
+     *        ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, FCONST_0,
+     *        FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, LALOAD, FALOAD,
+     *        DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IASTORE, LASTORE, FASTORE,
+     *        DASTORE, AASTORE, BASTORE, CASTORE, SASTORE, POP, POP2, DUP,
+     *        DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP, IADD, LADD, FADD,
+     *        DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, LDIV,
+     *        FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL,
+     *        LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR,
+     *        I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B,
+     *        I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN,
+     *        FRETURN, DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW,
+     *        MONITORENTER, or MONITOREXIT.
+     */
+    void visitInsn(int opcode);
+
+    /**
+     * Visits an instruction with a single int operand.
+     * 
+     * @param opcode the opcode of the instruction to be visited. This opcode is
+     *        either BIPUSH, SIPUSH or NEWARRAY.
+     * @param operand the operand of the instruction to be visited.<br>
+     *        When opcode is BIPUSH, operand value should be between
+     *        Byte.MIN_VALUE and Byte.MAX_VALUE.<br>
+     *        When opcode is SIPUSH, operand value should be between
+     *        Short.MIN_VALUE and Short.MAX_VALUE.<br>
+     *        When opcode is NEWARRAY, operand value should be one of
+     *        {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR},
+     *        {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE},
+     *        {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT},
+     *        {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}.
+     */
+    void visitIntInsn(int opcode,
+                      int operand);
+
+    /**
+     * Visits a local variable instruction. A local variable instruction is an
+     * instruction that loads or stores the value of a local variable.
+     * 
+     * @param opcode the opcode of the local variable instruction to be visited.
+     *        This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE,
+     *        LSTORE, FSTORE, DSTORE, ASTORE or RET.
+     * @param var the operand of the instruction to be visited. This operand is
+     *        the index of a local variable.
+     */
+    void visitVarInsn(int opcode,
+                      int var);
+
+    /**
+     * Visits a type instruction. A type instruction is an instruction that
+     * takes a type descriptor as parameter.
+     * 
+     * @param opcode the opcode of the type instruction to be visited. This
+     *        opcode is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
+     * @param desc the operand of the instruction to be visited. This operand is
+     *        must be a fully qualified class name in internal form, or the type
+     *        descriptor of an array type (see {@link Type Type}).
+     */
+    void visitTypeInsn(int opcode,
+                       String desc);
+
+    /**
+     * Visits a field instruction. A field instruction is an instruction that
+     * loads or stores the value of a field of an object.
+     * 
+     * @param opcode the opcode of the type instruction to be visited. This
+     *        opcode is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
+     * @param owner the internal name of the field's owner class (see {@link
+     *        Type#getInternalName() getInternalName}).
+     * @param name the field's name.
+     * @param desc the field's descriptor (see {@link Type Type}).
+     */
+    void visitFieldInsn(int opcode,
+                        String owner,
+                        String name,
+                        String desc);
+
+    /**
+     * Visits a method instruction. A method instruction is an instruction that
+     * invokes a method.
+     * 
+     * @param opcode the opcode of the type instruction to be visited. This
+     *        opcode is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
+     *        INVOKEINTERFACE.
+     * @param owner the internal name of the method's owner class (see {@link
+     *        Type#getInternalName() getInternalName}).
+     * @param name the method's name.
+     * @param desc the method's descriptor (see {@link Type Type}).
+     */
+    void visitMethodInsn(int opcode,
+                         String owner,
+                         String name,
+                         String desc);
+
+    /**
+     * Visits a jump instruction. A jump instruction is an instruction that may
+     * jump to another instruction.
+     * 
+     * @param opcode the opcode of the type instruction to be visited. This
+     *        opcode is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
+     *        IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ,
+     *        IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
+     * @param label the operand of the instruction to be visited. This operand
+     *        is a label that designates the instruction to which the jump
+     *        instruction may jump.
+     */
+    void visitJumpInsn(int opcode,
+                       Label label);
+
+    /**
+     * Visits a label. A label designates the instruction that will be visited
+     * just after it.
+     * 
+     * @param label a {@link Label Label} object.
+     */
+    void visitLabel(Label label);
+
+    // -------------------------------------------------------------------------
+    // Special instructions
+    // -------------------------------------------------------------------------
+
+    /**
+     * Visits a LDC instruction.
+     * 
+     * @param cst the constant to be loaded on the stack. This parameter must be
+     *        a non null {@link Integer}, a {@link Float}, a {@link Long}, a
+     *        {@link Double} a {@link String} (or a {@link Type} for
+     *        <tt>.class</tt> constants, for classes whose version is 49.0 or
+     *        more).
+     */
+    void visitLdcInsn(Object cst);
+
+    /**
+     * Visits an IINC instruction.
+     * 
+     * @param var index of the local variable to be incremented.
+     * @param increment amount to increment the local variable by.
+     */
+    void visitIincInsn(int var,
+                       int increment);
+
+    /**
+     * Visits a TABLESWITCH instruction.
+     * 
+     * @param min the minimum key value.
+     * @param min the maximum key value.
+     * @param dflt beginning of the default handler block.
+     * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
+     *        the beginning of the handler block for the <tt>min + i</tt> key.
+     */
+    void visitTableSwitchInsn(int min,
+                              int max,
+                              Label dflt,
+                              Label labels[]);
+
+    /**
+     * Visits a LOOKUPSWITCH instruction.
+     * 
+     * @param dflt beginning of the default handler block.
+     * @param keys the values of the keys.
+     * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
+     *        the beginning of the handler block for the <tt>keys[i]</tt> key.
+     */
+    void visitLookupSwitchInsn(Label dflt,
+                               int keys[],
+                               Label labels[]);
+
+    /**
+     * Visits a MULTIANEWARRAY instruction.
+     * 
+     * @param desc an array type descriptor (see {@link Type Type}).
+     * @param dims number of dimensions of the array to allocate.
+     */
+    void visitMultiANewArrayInsn(String desc,
+                                 int dims);
+
+    // -------------------------------------------------------------------------
+    // Exceptions table entries, debug information,
+    // min stack size and min locals
+    // -------------------------------------------------------------------------
+
+    /**
+     * Visits a try catch block.
+     * 
+     * @param start beginning of the exception handler's scope (inclusive).
+     * @param end end of the exception handler's scope (exclusive).
+     * @param handler beginning of the exception handler's code.
+     * @param type internal name of the type of exceptions handled by the
+     *        handler, or <tt>null</tt> to catch any exceptions (for "finally"
+     *        blocks).
+     */
+    void visitTryCatchBlock(Label start,
+                            Label end,
+                            Label handler,
+                            String type);
+
+    /**
+     * Visits a local variable declaration.
+     * 
+     * @param name the name of a local variable.
+     * @param desc the type descriptor of this local variable.
+     * @param signature the type signature of this local variable. May be
+     *        <tt>null</tt> if the local variable type does not use generic
+     *        types.
+     * @param start the first instruction corresponding to the scope of this
+     *        local variable (inclusive).
+     * @param end the last instruction corresponding to the scope of this local
+     *        variable (exclusive).
+     * @param index the local variable's index.
+     * @throws IllegalArgumentException if one of the labels has not already
+     *         been visited by this visitor (by the
+     *         {@link #visitLabel visitLabel} method).
+     */
+    void visitLocalVariable(String name,
+                            String desc,
+                            String signature,
+                            Label start,
+                            Label end,
+                            int index);
+
+    /**
+     * Visits a line number declaration.
+     * 
+     * @param line a line number. This number refers to the source file from
+     *        which the class was compiled.
+     * @param start the first instruction corresponding to this line number.
+     * @throws IllegalArgumentException if <tt>start</tt> has not already been
+     *         visited by this visitor (by the {@link #visitLabel visitLabel}
+     *         method).
+     */
+    void visitLineNumber(int line,
+                         Label start);
+
+    /**
+     * Visits the maximum stack size and the maximum number of local variables
+     * of the method.
+     * 
+     * @param maxStack maximum stack size of the method.
+     * @param maxLocals maximum number of local variables for the method.
+     */
+    void visitMaxs(int maxStack,
+                   int maxLocals);
+
+    /**
+     * Visits the end of the method. This method, which is the last one to be
+     * called, is used to inform the visitor that all the annotations and
+     * attributes of the method have been visited.
+     */
+    void visitEnd();
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/MethodWriter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/MethodWriter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/MethodWriter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,2148 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm;
+
+/**
+ * A {@link MethodVisitor} that generates methods in bytecode form. Each visit
+ * method of this class appends the bytecode corresponding to the visited
+ * instruction to a byte vector, in the order these methods are called.
+ * 
+ * @author Eric Bruneton
+ */
+class MethodWriter
+    implements
+    MethodVisitor {
+
+    /**
+     * Next method writer (see {@link ClassWriter#firstMethod firstMethod}).
+     */
+    MethodWriter               next;
+
+    /**
+     * The class writer to which this method must be added.
+     */
+    ClassWriter                cw;
+
+    /**
+     * Access flags of this method.
+     */
+    private int                access;
+
+    /**
+     * The index of the constant pool item that contains the name of this
+     * method.
+     */
+    private int                name;
+
+    /**
+     * The index of the constant pool item that contains the descriptor of this
+     * method.
+     */
+    private int                desc;
+
+    /**
+     * The descriptor of this method.
+     */
+    private String             descriptor;
+
+    /**
+     * If not zero, indicates that the code of this method must be copied from
+     * the ClassReader associated to this writer in <code>cw.cr</code>. More
+     * precisely, this field gives the index of the first byte to copied from
+     * <code>cw.cr.b</code>.
+     */
+    int                        classReaderOffset;
+
+    /**
+     * If not zero, indicates that the code of this method must be copied from
+     * the ClassReader associated to this writer in <code>cw.cr</code>. More
+     * precisely, this field gives the number of bytes to copied from
+     * <code>cw.cr.b</code>.
+     */
+    int                        classReaderLength;
+
+    /**
+     * The signature of this method.
+     */
+    String                     signature;
+
+    /**
+     * Number of exceptions that can be thrown by this method.
+     */
+    int                        exceptionCount;
+
+    /**
+     * The exceptions that can be thrown by this method. More precisely, this
+     * array contains the indexes of the constant pool items that contain the
+     * internal names of these exception classes.
+     */
+    int[]                      exceptions;
+
+    /**
+     * The annotation default attribute of this method. May be <tt>null</tt>.
+     */
+    private ByteVector         annd;
+
+    /**
+     * The runtime visible annotations of this method. May be <tt>null</tt>.
+     */
+    private AnnotationWriter   anns;
+
+    /**
+     * The runtime invisible annotations of this method. May be <tt>null</tt>.
+     */
+    private AnnotationWriter   ianns;
+
+    /**
+     * The runtime visible parameter annotations of this method. May be
+     * <tt>null</tt>.
+     */
+    private AnnotationWriter[] panns;
+
+    /**
+     * The runtime invisible parameter annotations of this method. May be
+     * <tt>null</tt>.
+     */
+    private AnnotationWriter[] ipanns;
+
+    /**
+     * The non standard attributes of the method.
+     */
+    private Attribute          attrs;
+
+    /**
+     * The bytecode of this method.
+     */
+    private ByteVector         code = new ByteVector();
+
+    /**
+     * Maximum stack size of this method.
+     */
+    private int                maxStack;
+
+    /**
+     * Maximum number of local variables for this method.
+     */
+    private int                maxLocals;
+
+    /**
+     * Number of entries in the catch table of this method.
+     */
+    private int                catchCount;
+
+    /**
+     * The catch table of this method.
+     */
+    private Handler            catchTable;
+
+    /**
+     * The last element in the catchTable handler list.
+     */
+    private Handler            lastHandler;
+
+    /**
+     * Number of entries in the LocalVariableTable attribute.
+     */
+    private int                localVarCount;
+
+    /**
+     * The LocalVariableTable attribute.
+     */
+    private ByteVector         localVar;
+
+    /**
+     * Number of entries in the LocalVariableTypeTable attribute.
+     */
+    private int                localVarTypeCount;
+
+    /**
+     * The LocalVariableTypeTable attribute.
+     */
+    private ByteVector         localVarType;
+
+    /**
+     * Number of entries in the LineNumberTable attribute.
+     */
+    private int                lineNumberCount;
+
+    /**
+     * The LineNumberTable attribute.
+     */
+    private ByteVector         lineNumber;
+
+    /**
+     * The non standard attributes of the method's code.
+     */
+    private Attribute          cattrs;
+
+    /**
+     * Indicates if some jump instructions are too small and need to be resized.
+     */
+    private boolean            resize;
+
+    /*
+     * Fields for the control flow graph analysis algorithm (used to compute the
+     * maximum stack size). A control flow graph contains one node per "basic
+     * block", and one edge per "jump" from one basic block to another. Each
+     * node (i.e., each basic block) is represented by the Label object that
+     * corresponds to the first instruction of this basic block. Each node also
+     * stores the list of its successors in the graph, as a linked list of Edge
+     * objects.
+     */
+
+    /**
+     * <tt>true</tt> if the maximum stack size and number of local variables
+     * must be automatically computed.
+     */
+    private final boolean      computeMaxs;
+
+    /**
+     * The (relative) stack size after the last visited instruction. This size
+     * is relative to the beginning of the current basic block, i.e., the true
+     * stack size after the last visited instruction is equal to the {@link
+     * Label#beginStackSize beginStackSize} of the current basic block plus
+     * <tt>stackSize</tt>.
+     */
+    private int                stackSize;
+
+    /**
+     * The (relative) maximum stack size after the last visited instruction.
+     * This size is relative to the beginning of the current basic block, i.e.,
+     * the true maximum stack size after the last visited instruction is equal
+     * to the {@link Label#beginStackSize beginStackSize} of the current basic
+     * block plus <tt>stackSize</tt>.
+     */
+    private int                maxStackSize;
+
+    /**
+     * The current basic block. This block is the basic block to which the next
+     * instruction to be visited must be added.
+     */
+    private Label              currentBlock;
+
+    /**
+     * The basic block stack used by the control flow analysis algorithm. This
+     * stack is represented by a linked list of {@link Label Label} objects,
+     * linked to each other by their {@link Label#next} field. This stack must
+     * not be confused with the JVM stack used to execute the JVM instructions!
+     */
+    private Label              blockStack;
+
+    /**
+     * The stack size variation corresponding to each JVM instruction. This
+     * stack variation is equal to the size of the values produced by an
+     * instruction, minus the size of the values consumed by this instruction.
+     */
+    private final static int[] SIZE;
+
+    // ------------------------------------------------------------------------
+    // Static initializer
+    // ------------------------------------------------------------------------
+
+    /**
+     * Computes the stack size variation corresponding to each JVM instruction.
+     */
+    static {
+        int i;
+        final int[] b = new int[202];
+        final String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD" + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD" + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED" + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE";
+        for ( i = 0; i < b.length; ++i ) {
+            b[i] = s.charAt( i ) - 'E';
+        }
+        SIZE = b;
+
+        // code to generate the above string
+        //
+        // int NA = 0; // not applicable (unused opcode or variable size opcode)
+        //
+        // b = new int[] {
+        // 0, //NOP, // visitInsn
+        // 1, //ACONST_NULL, // -
+        // 1, //ICONST_M1, // -
+        // 1, //ICONST_0, // -
+        // 1, //ICONST_1, // -
+        // 1, //ICONST_2, // -
+        // 1, //ICONST_3, // -
+        // 1, //ICONST_4, // -
+        // 1, //ICONST_5, // -
+        // 2, //LCONST_0, // -
+        // 2, //LCONST_1, // -
+        // 1, //FCONST_0, // -
+        // 1, //FCONST_1, // -
+        // 1, //FCONST_2, // -
+        // 2, //DCONST_0, // -
+        // 2, //DCONST_1, // -
+        // 1, //BIPUSH, // visitIntInsn
+        // 1, //SIPUSH, // -
+        // 1, //LDC, // visitLdcInsn
+        // NA, //LDC_W, // -
+        // NA, //LDC2_W, // -
+        // 1, //ILOAD, // visitVarInsn
+        // 2, //LLOAD, // -
+        // 1, //FLOAD, // -
+        // 2, //DLOAD, // -
+        // 1, //ALOAD, // -
+        // NA, //ILOAD_0, // -
+        // NA, //ILOAD_1, // -
+        // NA, //ILOAD_2, // -
+        // NA, //ILOAD_3, // -
+        // NA, //LLOAD_0, // -
+        // NA, //LLOAD_1, // -
+        // NA, //LLOAD_2, // -
+        // NA, //LLOAD_3, // -
+        // NA, //FLOAD_0, // -
+        // NA, //FLOAD_1, // -
+        // NA, //FLOAD_2, // -
+        // NA, //FLOAD_3, // -
+        // NA, //DLOAD_0, // -
+        // NA, //DLOAD_1, // -
+        // NA, //DLOAD_2, // -
+        // NA, //DLOAD_3, // -
+        // NA, //ALOAD_0, // -
+        // NA, //ALOAD_1, // -
+        // NA, //ALOAD_2, // -
+        // NA, //ALOAD_3, // -
+        // -1, //IALOAD, // visitInsn
+        // 0, //LALOAD, // -
+        // -1, //FALOAD, // -
+        // 0, //DALOAD, // -
+        // -1, //AALOAD, // -
+        // -1, //BALOAD, // -
+        // -1, //CALOAD, // -
+        // -1, //SALOAD, // -
+        // -1, //ISTORE, // visitVarInsn
+        // -2, //LSTORE, // -
+        // -1, //FSTORE, // -
+        // -2, //DSTORE, // -
+        // -1, //ASTORE, // -
+        // NA, //ISTORE_0, // -
+        // NA, //ISTORE_1, // -
+        // NA, //ISTORE_2, // -
+        // NA, //ISTORE_3, // -
+        // NA, //LSTORE_0, // -
+        // NA, //LSTORE_1, // -
+        // NA, //LSTORE_2, // -
+        // NA, //LSTORE_3, // -
+        // NA, //FSTORE_0, // -
+        // NA, //FSTORE_1, // -
+        // NA, //FSTORE_2, // -
+        // NA, //FSTORE_3, // -
+        // NA, //DSTORE_0, // -
+        // NA, //DSTORE_1, // -
+        // NA, //DSTORE_2, // -
+        // NA, //DSTORE_3, // -
+        // NA, //ASTORE_0, // -
+        // NA, //ASTORE_1, // -
+        // NA, //ASTORE_2, // -
+        // NA, //ASTORE_3, // -
+        // -3, //IASTORE, // visitInsn
+        // -4, //LASTORE, // -
+        // -3, //FASTORE, // -
+        // -4, //DASTORE, // -
+        // -3, //AASTORE, // -
+        // -3, //BASTORE, // -
+        // -3, //CASTORE, // -
+        // -3, //SASTORE, // -
+        // -1, //POP, // -
+        // -2, //POP2, // -
+        // 1, //DUP, // -
+        // 1, //DUP_X1, // -
+        // 1, //DUP_X2, // -
+        // 2, //DUP2, // -
+        // 2, //DUP2_X1, // -
+        // 2, //DUP2_X2, // -
+        // 0, //SWAP, // -
+        // -1, //IADD, // -
+        // -2, //LADD, // -
+        // -1, //FADD, // -
+        // -2, //DADD, // -
+        // -1, //ISUB, // -
+        // -2, //LSUB, // -
+        // -1, //FSUB, // -
+        // -2, //DSUB, // -
+        // -1, //IMUL, // -
+        // -2, //LMUL, // -
+        // -1, //FMUL, // -
+        // -2, //DMUL, // -
+        // -1, //IDIV, // -
+        // -2, //LDIV, // -
+        // -1, //FDIV, // -
+        // -2, //DDIV, // -
+        // -1, //IREM, // -
+        // -2, //LREM, // -
+        // -1, //FREM, // -
+        // -2, //DREM, // -
+        // 0, //INEG, // -
+        // 0, //LNEG, // -
+        // 0, //FNEG, // -
+        // 0, //DNEG, // -
+        // -1, //ISHL, // -
+        // -1, //LSHL, // -
+        // -1, //ISHR, // -
+        // -1, //LSHR, // -
+        // -1, //IUSHR, // -
+        // -1, //LUSHR, // -
+        // -1, //IAND, // -
+        // -2, //LAND, // -
+        // -1, //IOR, // -
+        // -2, //LOR, // -
+        // -1, //IXOR, // -
+        // -2, //LXOR, // -
+        // 0, //IINC, // visitIincInsn
+        // 1, //I2L, // visitInsn
+        // 0, //I2F, // -
+        // 1, //I2D, // -
+        // -1, //L2I, // -
+        // -1, //L2F, // -
+        // 0, //L2D, // -
+        // 0, //F2I, // -
+        // 1, //F2L, // -
+        // 1, //F2D, // -
+        // -1, //D2I, // -
+        // 0, //D2L, // -
+        // -1, //D2F, // -
+        // 0, //I2B, // -
+        // 0, //I2C, // -
+        // 0, //I2S, // -
+        // -3, //LCMP, // -
+        // -1, //FCMPL, // -
+        // -1, //FCMPG, // -
+        // -3, //DCMPL, // -
+        // -3, //DCMPG, // -
+        // -1, //IFEQ, // visitJumpInsn
+        // -1, //IFNE, // -
+        // -1, //IFLT, // -
+        // -1, //IFGE, // -
+        // -1, //IFGT, // -
+        // -1, //IFLE, // -
+        // -2, //IF_ICMPEQ, // -
+        // -2, //IF_ICMPNE, // -
+        // -2, //IF_ICMPLT, // -
+        // -2, //IF_ICMPGE, // -
+        // -2, //IF_ICMPGT, // -
+        // -2, //IF_ICMPLE, // -
+        // -2, //IF_ACMPEQ, // -
+        // -2, //IF_ACMPNE, // -
+        // 0, //GOTO, // -
+        // 1, //JSR, // -
+        // 0, //RET, // visitVarInsn
+        // -1, //TABLESWITCH, // visiTableSwitchInsn
+        // -1, //LOOKUPSWITCH, // visitLookupSwitch
+        // -1, //IRETURN, // visitInsn
+        // -2, //LRETURN, // -
+        // -1, //FRETURN, // -
+        // -2, //DRETURN, // -
+        // -1, //ARETURN, // -
+        // 0, //RETURN, // -
+        // NA, //GETSTATIC, // visitFieldInsn
+        // NA, //PUTSTATIC, // -
+        // NA, //GETFIELD, // -
+        // NA, //PUTFIELD, // -
+        // NA, //INVOKEVIRTUAL, // visitMethodInsn
+        // NA, //INVOKESPECIAL, // -
+        // NA, //INVOKESTATIC, // -
+        // NA, //INVOKEINTERFACE, // -
+        // NA, //UNUSED, // NOT VISITED
+        // 1, //NEW, // visitTypeInsn
+        // 0, //NEWARRAY, // visitIntInsn
+        // 0, //ANEWARRAY, // visitTypeInsn
+        // 0, //ARRAYLENGTH, // visitInsn
+        // NA, //ATHROW, // -
+        // 0, //CHECKCAST, // visitTypeInsn
+        // 0, //INSTANCEOF, // -
+        // -1, //MONITORENTER, // visitInsn
+        // -1, //MONITOREXIT, // -
+        // NA, //WIDE, // NOT VISITED
+        // NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn
+        // -1, //IFNULL, // visitJumpInsn
+        // -1, //IFNONNULL, // -
+        // NA, //GOTO_W, // -
+        // NA, //JSR_W, // -
+        // };
+        // for (i = 0; i < b.length; ++i) {
+        // System.err.print((char)('E' + b[i]));
+        // }
+        // System.err.println();
+    }
+
+    // ------------------------------------------------------------------------
+    // Constructor
+    // ------------------------------------------------------------------------
+
+    /**
+     * Constructs a new {@link MethodWriter}.
+     * 
+     * @param cw the class writer in which the method must be added.
+     * @param access the method's access flags (see {@link Opcodes}).
+     * @param name the method's name.
+     * @param desc the method's descriptor (see {@link Type}).
+     * @param signature the method's signature. May be <tt>null</tt>.
+     * @param exceptions the internal names of the method's exceptions. May be
+     *        <tt>null</tt>.
+     * @param computeMaxs <tt>true</tt> if the maximum stack size and number
+     *        of local variables must be automatically computed.
+     */
+    MethodWriter(final ClassWriter cw,
+                 final int access,
+                 final String name,
+                 final String desc,
+                 final String signature,
+                 final String[] exceptions,
+                 final boolean computeMaxs) {
+        if ( cw.firstMethod == null ) {
+            cw.firstMethod = this;
+        } else {
+            cw.lastMethod.next = this;
+        }
+        cw.lastMethod = this;
+        this.cw = cw;
+        this.access = access;
+        this.name = cw.newUTF8( name );
+        this.desc = cw.newUTF8( desc );
+        this.descriptor = desc;
+        this.signature = signature;
+        if ( exceptions != null && exceptions.length > 0 ) {
+            this.exceptionCount = exceptions.length;
+            this.exceptions = new int[this.exceptionCount];
+            for ( int i = 0; i < this.exceptionCount; ++i ) {
+                this.exceptions[i] = cw.newClass( exceptions[i] );
+            }
+        }
+        this.computeMaxs = computeMaxs;
+        if ( computeMaxs ) {
+            // updates maxLocals
+            int size = getArgumentsAndReturnSizes( desc ) >> 2;
+            if ( (access & Opcodes.ACC_STATIC) != 0 ) {
+                --size;
+            }
+            this.maxLocals = size;
+            // pushes the first block onto the stack of blocks to be visited
+            this.currentBlock = new Label();
+            this.currentBlock.pushed = true;
+            this.blockStack = this.currentBlock;
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Implementation of the MethodVisitor interface
+    // ------------------------------------------------------------------------
+
+    public AnnotationVisitor visitAnnotationDefault() {
+        this.annd = new ByteVector();
+        return new AnnotationWriter( this.cw,
+                                     false,
+                                     this.annd,
+                                     null,
+                                     0 );
+    }
+
+    public AnnotationVisitor visitAnnotation(final String desc,
+                                             final boolean visible) {
+        final ByteVector bv = new ByteVector();
+        // write type, and reserve space for values count
+        bv.putShort( this.cw.newUTF8( desc ) ).putShort( 0 );
+        final AnnotationWriter aw = new AnnotationWriter( this.cw,
+                                                          true,
+                                                          bv,
+                                                          bv,
+                                                          2 );
+        if ( visible ) {
+            aw.next = this.anns;
+            this.anns = aw;
+        } else {
+            aw.next = this.ianns;
+            this.ianns = aw;
+        }
+        return aw;
+    }
+
+    public AnnotationVisitor visitParameterAnnotation(final int parameter,
+                                                      final String desc,
+                                                      final boolean visible) {
+        final ByteVector bv = new ByteVector();
+        // write type, and reserve space for values count
+        bv.putShort( this.cw.newUTF8( desc ) ).putShort( 0 );
+        final AnnotationWriter aw = new AnnotationWriter( this.cw,
+                                                          true,
+                                                          bv,
+                                                          bv,
+                                                          2 );
+        if ( visible ) {
+            if ( this.panns == null ) {
+                this.panns = new AnnotationWriter[Type.getArgumentTypes( this.descriptor ).length];
+            }
+            aw.next = this.panns[parameter];
+            this.panns[parameter] = aw;
+        } else {
+            if ( this.ipanns == null ) {
+                this.ipanns = new AnnotationWriter[Type.getArgumentTypes( this.descriptor ).length];
+            }
+            aw.next = this.ipanns[parameter];
+            this.ipanns[parameter] = aw;
+        }
+        return aw;
+    }
+
+    public void visitAttribute(final Attribute attr) {
+        if ( attr.isCodeAttribute() ) {
+            attr.next = this.cattrs;
+            this.cattrs = attr;
+        } else {
+            attr.next = this.attrs;
+            this.attrs = attr;
+        }
+    }
+
+    public void visitCode() {
+    }
+
+    public void visitInsn(final int opcode) {
+        if ( this.computeMaxs ) {
+            // updates current and min stack sizes
+            final int size = this.stackSize + MethodWriter.SIZE[opcode];
+            if ( size > this.maxStackSize ) {
+                this.maxStackSize = size;
+            }
+            this.stackSize = size;
+            // if opcode == ATHROW or xRETURN, ends current block (no successor)
+            if ( (opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) || opcode == Opcodes.ATHROW ) {
+                if ( this.currentBlock != null ) {
+                    this.currentBlock.maxStackSize = this.maxStackSize;
+                    this.currentBlock = null;
+                }
+            }
+        }
+        // adds the instruction to the bytecode of the method
+        this.code.putByte( opcode );
+    }
+
+    public void visitIntInsn(final int opcode,
+                             final int operand) {
+        if ( this.computeMaxs && opcode != Opcodes.NEWARRAY ) {
+            // updates current and min stack sizes only if opcode == NEWARRAY
+            // (stack size variation = 0 for BIPUSH or SIPUSH)
+            final int size = this.stackSize + 1;
+            if ( size > this.maxStackSize ) {
+                this.maxStackSize = size;
+            }
+            this.stackSize = size;
+        }
+        // adds the instruction to the bytecode of the method
+        if ( opcode == Opcodes.SIPUSH ) {
+            this.code.put12( opcode,
+                             operand );
+        } else { // BIPUSH or NEWARRAY
+            this.code.put11( opcode,
+                             operand );
+        }
+    }
+
+    public void visitVarInsn(final int opcode,
+                             final int var) {
+        if ( this.computeMaxs ) {
+            // updates current and min stack sizes
+            if ( opcode == Opcodes.RET ) {
+                // no stack change, but end of current block (no successor)
+                if ( this.currentBlock != null ) {
+                    this.currentBlock.maxStackSize = this.maxStackSize;
+                    this.currentBlock = null;
+                }
+            } else { // xLOAD or xSTORE
+                final int size = this.stackSize + MethodWriter.SIZE[opcode];
+                if ( size > this.maxStackSize ) {
+                    this.maxStackSize = size;
+                }
+                this.stackSize = size;
+            }
+            // updates min locals
+            int n;
+            if ( opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE ) {
+                n = var + 2;
+            } else {
+                n = var + 1;
+            }
+            if ( n > this.maxLocals ) {
+                this.maxLocals = n;
+            }
+        }
+        // adds the instruction to the bytecode of the method
+        if ( var < 4 && opcode != Opcodes.RET ) {
+            int opt;
+            if ( opcode < Opcodes.ISTORE ) {
+                /* ILOAD_0 */
+                opt = 26 + ((opcode - Opcodes.ILOAD) << 2) + var;
+            } else {
+                /* ISTORE_0 */
+                opt = 59 + ((opcode - Opcodes.ISTORE) << 2) + var;
+            }
+            this.code.putByte( opt );
+        } else if ( var >= 256 ) {
+            this.code.putByte( 196 /* WIDE */).put12( opcode,
+                                                       var );
+        } else {
+            this.code.put11( opcode,
+                             var );
+        }
+    }
+
+    public void visitTypeInsn(final int opcode,
+                              final String desc) {
+        if ( this.computeMaxs && opcode == Opcodes.NEW ) {
+            // updates current and min stack sizes only if opcode == NEW
+            // (stack size variation = 0 for ANEWARRAY, CHECKCAST, INSTANCEOF)
+            final int size = this.stackSize + 1;
+            if ( size > this.maxStackSize ) {
+                this.maxStackSize = size;
+            }
+            this.stackSize = size;
+        }
+        // adds the instruction to the bytecode of the method
+        this.code.put12( opcode,
+                         this.cw.newClass( desc ) );
+    }
+
+    public void visitFieldInsn(final int opcode,
+                               final String owner,
+                               final String name,
+                               final String desc) {
+        if ( this.computeMaxs ) {
+            int size;
+            // computes the stack size variation
+            final char c = desc.charAt( 0 );
+            switch ( opcode ) {
+                case Opcodes.GETSTATIC :
+                    size = this.stackSize + (c == 'D' || c == 'J' ? 2 : 1);
+                    break;
+                case Opcodes.PUTSTATIC :
+                    size = this.stackSize + (c == 'D' || c == 'J' ? -2 : -1);
+                    break;
+                case Opcodes.GETFIELD :
+                    size = this.stackSize + (c == 'D' || c == 'J' ? 1 : 0);
+                    break;
+                // case Constants.PUTFIELD:
+                default :
+                    size = this.stackSize + (c == 'D' || c == 'J' ? -3 : -2);
+                    break;
+            }
+            // updates current and min stack sizes
+            if ( size > this.maxStackSize ) {
+                this.maxStackSize = size;
+            }
+            this.stackSize = size;
+        }
+        // adds the instruction to the bytecode of the method
+        this.code.put12( opcode,
+                         this.cw.newField( owner,
+                                           name,
+                                           desc ) );
+    }
+
+    public void visitMethodInsn(final int opcode,
+                                final String owner,
+                                final String name,
+                                final String desc) {
+        final boolean itf = opcode == Opcodes.INVOKEINTERFACE;
+        final Item i = this.cw.newMethodItem( owner,
+                                              name,
+                                              desc,
+                                              itf );
+        int argSize = i.intVal;
+        if ( this.computeMaxs ) {
+            /*
+             * computes the stack size variation. In order not to recompute
+             * several times this variation for the same Item, we use the intVal
+             * field of this item to store this variation, once it has been
+             * computed. More precisely this intVal field stores the sizes of
+             * the arguments and of the return value corresponding to desc.
+             */
+            if ( argSize == 0 ) {
+                // the above sizes have not been computed yet, so we compute
+                // them...
+                argSize = getArgumentsAndReturnSizes( desc );
+                // ... and we save them in order not to recompute them in the
+                // future
+                i.intVal = argSize;
+            }
+            int size;
+            if ( opcode == Opcodes.INVOKESTATIC ) {
+                size = this.stackSize - (argSize >> 2) + (argSize & 0x03) + 1;
+            } else {
+                size = this.stackSize - (argSize >> 2) + (argSize & 0x03);
+            }
+            // updates current and min stack sizes
+            if ( size > this.maxStackSize ) {
+                this.maxStackSize = size;
+            }
+            this.stackSize = size;
+        }
+        // adds the instruction to the bytecode of the method
+        if ( itf ) {
+            if ( !this.computeMaxs ) {
+                if ( argSize == 0 ) {
+                    argSize = getArgumentsAndReturnSizes( desc );
+                    i.intVal = argSize;
+                }
+            }
+            this.code.put12( Opcodes.INVOKEINTERFACE,
+                             i.index ).put11( argSize >> 2,
+                                              0 );
+        } else {
+            this.code.put12( opcode,
+                             i.index );
+        }
+    }
+
+    public void visitJumpInsn(final int opcode,
+                              final Label label) {
+        if ( this.computeMaxs ) {
+            if ( opcode == Opcodes.GOTO ) {
+                // no stack change, but end of current block (with one new
+                // successor)
+                if ( this.currentBlock != null ) {
+                    this.currentBlock.maxStackSize = this.maxStackSize;
+                    addSuccessor( this.stackSize,
+                                  label );
+                    this.currentBlock = null;
+                }
+            } else if ( opcode == Opcodes.JSR ) {
+                if ( this.currentBlock != null ) {
+                    addSuccessor( this.stackSize + 1,
+                                  label );
+                }
+            } else {
+                // updates current stack size (min stack size unchanged because
+                // stack size variation always negative in this case)
+                this.stackSize += MethodWriter.SIZE[opcode];
+                if ( this.currentBlock != null ) {
+                    addSuccessor( this.stackSize,
+                                  label );
+                }
+            }
+        }
+        // adds the instruction to the bytecode of the method
+        if ( label.resolved && label.position - this.code.length < Short.MIN_VALUE ) {
+            /*
+             * case of a backward jump with an offset < -32768. In this case we
+             * automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx
+             * <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is the
+             * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where <l'>
+             * designates the instruction just after the GOTO_W.
+             */
+            if ( opcode == Opcodes.GOTO ) {
+                this.code.putByte( 200 ); // GOTO_W
+            } else if ( opcode == Opcodes.JSR ) {
+                this.code.putByte( 201 ); // JSR_W
+            } else {
+                this.code.putByte( opcode <= 166 ? ((opcode + 1) ^ 1) - 1 : opcode ^ 1 );
+                this.code.putShort( 8 ); // jump offset
+                this.code.putByte( 200 ); // GOTO_W
+            }
+            label.put( this,
+                       this.code,
+                       this.code.length - 1,
+                       true );
+        } else {
+            /*
+             * case of a backward jump with an offset >= -32768, or of a forward
+             * jump with, of course, an unknown offset. In these cases we store
+             * the offset in 2 bytes (which will be increased in
+             * resizeInstructions, if needed).
+             */
+            this.code.putByte( opcode );
+            label.put( this,
+                       this.code,
+                       this.code.length - 1,
+                       false );
+        }
+    }
+
+    public void visitLabel(final Label label) {
+        if ( this.computeMaxs ) {
+            if ( this.currentBlock != null ) {
+                // ends current block (with one new successor)
+                this.currentBlock.maxStackSize = this.maxStackSize;
+                addSuccessor( this.stackSize,
+                              label );
+            }
+            // begins a new current block,
+            // resets the relative current and min stack sizes
+            this.currentBlock = label;
+            this.stackSize = 0;
+            this.maxStackSize = 0;
+        }
+        // resolves previous forward references to label, if any
+        this.resize |= label.resolve( this,
+                                      this.code.length,
+                                      this.code.data );
+    }
+
+    public void visitLdcInsn(final Object cst) {
+        final Item i = this.cw.newConstItem( cst );
+        if ( this.computeMaxs ) {
+            int size;
+            // computes the stack size variation
+            if ( i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE ) {
+                size = this.stackSize + 2;
+            } else {
+                size = this.stackSize + 1;
+            }
+            // updates current and min stack sizes
+            if ( size > this.maxStackSize ) {
+                this.maxStackSize = size;
+            }
+            this.stackSize = size;
+        }
+        // adds the instruction to the bytecode of the method
+        final int index = i.index;
+        if ( i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE ) {
+            this.code.put12( 20 /* LDC2_W */,
+                             index );
+        } else if ( index >= 256 ) {
+            this.code.put12( 19 /* LDC_W */,
+                             index );
+        } else {
+            this.code.put11( Opcodes.LDC,
+                             index );
+        }
+    }
+
+    public void visitIincInsn(final int var,
+                              final int increment) {
+        if ( this.computeMaxs ) {
+            // updates min locals only (no stack change)
+            final int n = var + 1;
+            if ( n > this.maxLocals ) {
+                this.maxLocals = n;
+            }
+        }
+        // adds the instruction to the bytecode of the method
+        if ( (var > 255) || (increment > 127) || (increment < -128) ) {
+            this.code.putByte( 196 /* WIDE */).put12( Opcodes.IINC,
+                                                       var ).putShort( increment );
+        } else {
+            this.code.putByte( Opcodes.IINC ).put11( var,
+                                                     increment );
+        }
+    }
+
+    public void visitTableSwitchInsn(final int min,
+                                     final int max,
+                                     final Label dflt,
+                                     final Label labels[]) {
+        if ( this.computeMaxs ) {
+            // updates current stack size (min stack size unchanged)
+            --this.stackSize;
+            // ends current block (with many new successors)
+            if ( this.currentBlock != null ) {
+                this.currentBlock.maxStackSize = this.maxStackSize;
+                addSuccessor( this.stackSize,
+                              dflt );
+                for ( int i = 0; i < labels.length; ++i ) {
+                    addSuccessor( this.stackSize,
+                                  labels[i] );
+                }
+                this.currentBlock = null;
+            }
+        }
+        // adds the instruction to the bytecode of the method
+        final int source = this.code.length;
+        this.code.putByte( Opcodes.TABLESWITCH );
+        while ( this.code.length % 4 != 0 ) {
+            this.code.putByte( 0 );
+        }
+        dflt.put( this,
+                  this.code,
+                  source,
+                  true );
+        this.code.putInt( min ).putInt( max );
+        for ( int i = 0; i < labels.length; ++i ) {
+            labels[i].put( this,
+                           this.code,
+                           source,
+                           true );
+        }
+    }
+
+    public void visitLookupSwitchInsn(final Label dflt,
+                                      final int keys[],
+                                      final Label labels[]) {
+        if ( this.computeMaxs ) {
+            // updates current stack size (min stack size unchanged)
+            --this.stackSize;
+            // ends current block (with many new successors)
+            if ( this.currentBlock != null ) {
+                this.currentBlock.maxStackSize = this.maxStackSize;
+                addSuccessor( this.stackSize,
+                              dflt );
+                for ( int i = 0; i < labels.length; ++i ) {
+                    addSuccessor( this.stackSize,
+                                  labels[i] );
+                }
+                this.currentBlock = null;
+            }
+        }
+        // adds the instruction to the bytecode of the method
+        final int source = this.code.length;
+        this.code.putByte( Opcodes.LOOKUPSWITCH );
+        while ( this.code.length % 4 != 0 ) {
+            this.code.putByte( 0 );
+        }
+        dflt.put( this,
+                  this.code,
+                  source,
+                  true );
+        this.code.putInt( labels.length );
+        for ( int i = 0; i < labels.length; ++i ) {
+            this.code.putInt( keys[i] );
+            labels[i].put( this,
+                           this.code,
+                           source,
+                           true );
+        }
+    }
+
+    public void visitMultiANewArrayInsn(final String desc,
+                                        final int dims) {
+        if ( this.computeMaxs ) {
+            // updates current stack size (min stack size unchanged because
+            // stack size variation always negative or null)
+            this.stackSize += 1 - dims;
+        }
+        // adds the instruction to the bytecode of the method
+        this.code.put12( Opcodes.MULTIANEWARRAY,
+                         this.cw.newClass( desc ) ).putByte( dims );
+    }
+
+    public void visitTryCatchBlock(final Label start,
+                                   final Label end,
+                                   final Label handler,
+                                   final String type) {
+        if ( this.computeMaxs ) {
+            // pushes handler block onto the stack of blocks to be visited
+            if ( !handler.pushed ) {
+                handler.beginStackSize = 1;
+                handler.pushed = true;
+                handler.next = this.blockStack;
+                this.blockStack = handler;
+            }
+        }
+        ++this.catchCount;
+        final Handler h = new Handler();
+        h.start = start;
+        h.end = end;
+        h.handler = handler;
+        h.desc = type;
+        h.type = type != null ? this.cw.newClass( type ) : 0;
+        if ( this.lastHandler == null ) {
+            this.catchTable = h;
+        } else {
+            this.lastHandler.next = h;
+        }
+        this.lastHandler = h;
+    }
+
+    public void visitLocalVariable(final String name,
+                                   final String desc,
+                                   final String signature,
+                                   final Label start,
+                                   final Label end,
+                                   final int index) {
+        if ( signature != null ) {
+            if ( this.localVarType == null ) {
+                this.localVarType = new ByteVector();
+            }
+            ++this.localVarTypeCount;
+            this.localVarType.putShort( start.position ).putShort( end.position - start.position ).putShort( this.cw.newUTF8( name ) ).putShort( this.cw.newUTF8( signature ) ).putShort( index );
+        }
+        if ( this.localVar == null ) {
+            this.localVar = new ByteVector();
+        }
+        ++this.localVarCount;
+        this.localVar.putShort( start.position ).putShort( end.position - start.position ).putShort( this.cw.newUTF8( name ) ).putShort( this.cw.newUTF8( desc ) ).putShort( index );
+    }
+
+    public void visitLineNumber(final int line,
+                                final Label start) {
+        if ( this.lineNumber == null ) {
+            this.lineNumber = new ByteVector();
+        }
+        ++this.lineNumberCount;
+        this.lineNumber.putShort( start.position );
+        this.lineNumber.putShort( line );
+    }
+
+    public void visitMaxs(final int maxStack,
+                          final int maxLocals) {
+        if ( this.computeMaxs ) {
+            // true (non relative) min stack size
+            int max = 0;
+            /*
+             * control flow analysis algorithm: while the block stack is not
+             * empty, pop a block from this stack, update the min stack size,
+             * compute the true (non relative) begin stack size of the
+             * successors of this block, and push these successors onto the
+             * stack (unless they have already been pushed onto the stack).
+             * Note: by hypothesis, the {@link Label#beginStackSize} of the
+             * blocks in the block stack are the true (non relative) beginning
+             * stack sizes of these blocks.
+             */
+            Label stack = this.blockStack;
+            while ( stack != null ) {
+                // pops a block from the stack
+                Label l = stack;
+                stack = stack.next;
+                // computes the true (non relative) min stack size of this block
+                final int start = l.beginStackSize;
+                final int blockMax = start + l.maxStackSize;
+                // updates the global min stack size
+                if ( blockMax > max ) {
+                    max = blockMax;
+                }
+                // analyses the successors of the block
+                Edge b = l.successors;
+                while ( b != null ) {
+                    l = b.successor;
+                    // if this successor has not already been pushed onto the
+                    // stack...
+                    if ( !l.pushed ) {
+                        // computes the true beginning stack size of this
+                        // successor block
+                        l.beginStackSize = start + b.stackSize;
+                        // pushes this successor onto the stack
+                        l.pushed = true;
+                        l.next = stack;
+                        stack = l;
+                    }
+                    b = b.next;
+                }
+            }
+            this.maxStack = max;
+        } else {
+            this.maxStack = maxStack;
+            this.maxLocals = maxLocals;
+        }
+    }
+
+    public void visitEnd() {
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods: control flow analysis algorithm
+    // ------------------------------------------------------------------------
+
+    /**
+     * Computes the size of the arguments and of the return value of a method.
+     * 
+     * @param desc the descriptor of a method.
+     * @return the size of the arguments of the method (plus one for the
+     *         implicit this argument), argSize, and the size of its return
+     *         value, retSize, packed into a single int i =
+     *         <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal
+     *         to <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>).
+     */
+    private static int getArgumentsAndReturnSizes(final String desc) {
+        int n = 1;
+        int c = 1;
+        while ( true ) {
+            char car = desc.charAt( c++ );
+            if ( car == ')' ) {
+                car = desc.charAt( c );
+                return n << 2 | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1));
+            } else if ( car == 'L' ) {
+                while ( desc.charAt( c++ ) != ';' ) {
+                }
+                n += 1;
+            } else if ( car == '[' ) {
+                while ( (car = desc.charAt( c )) == '[' ) {
+                    ++c;
+                }
+                if ( car == 'D' || car == 'J' ) {
+                    n -= 1;
+                }
+            } else if ( car == 'D' || car == 'J' ) {
+                n += 2;
+            } else {
+                n += 1;
+            }
+        }
+    }
+
+    /**
+     * Adds a successor to the {@link #currentBlock currentBlock} block.
+     * 
+     * @param stackSize the current (relative) stack size in the current block.
+     * @param successor the successor block to be added to the current block.
+     */
+    private void addSuccessor(final int stackSize,
+                              final Label successor) {
+        final Edge b = new Edge();
+        // initializes the previous Edge object...
+        b.stackSize = stackSize;
+        b.successor = successor;
+        // ...and adds it to the successor list of the currentBlock block
+        b.next = this.currentBlock.successors;
+        this.currentBlock.successors = b;
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods: dump bytecode array
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns the size of the bytecode of this method.
+     * 
+     * @return the size of the bytecode of this method.
+     */
+    final int getSize() {
+        if ( this.classReaderOffset != 0 ) {
+            return 6 + this.classReaderLength;
+        }
+        if ( this.resize ) {
+            // replaces the temporary jump opcodes introduced by Label.resolve.
+            resizeInstructions( new int[0],
+                                new int[0],
+                                0 );
+        }
+        int size = 8;
+        if ( this.code.length > 0 ) {
+            this.cw.newUTF8( "Code" );
+            size += 18 + this.code.length + 8 * this.catchCount;
+            if ( this.localVar != null ) {
+                this.cw.newUTF8( "LocalVariableTable" );
+                size += 8 + this.localVar.length;
+            }
+            if ( this.localVarType != null ) {
+                this.cw.newUTF8( "LocalVariableTypeTable" );
+                size += 8 + this.localVarType.length;
+            }
+            if ( this.lineNumber != null ) {
+                this.cw.newUTF8( "LineNumberTable" );
+                size += 8 + this.lineNumber.length;
+            }
+            if ( this.cattrs != null ) {
+                size += this.cattrs.getSize( this.cw,
+                                             this.code.data,
+                                             this.code.length,
+                                             this.maxStack,
+                                             this.maxLocals );
+            }
+        }
+        if ( this.exceptionCount > 0 ) {
+            this.cw.newUTF8( "Exceptions" );
+            size += 8 + 2 * this.exceptionCount;
+        }
+        if ( (this.access & Opcodes.ACC_SYNTHETIC) != 0 && (this.cw.version & 0xffff) < Opcodes.V1_5 ) {
+            this.cw.newUTF8( "Synthetic" );
+            size += 6;
+        }
+        if ( (this.access & Opcodes.ACC_DEPRECATED) != 0 ) {
+            this.cw.newUTF8( "Deprecated" );
+            size += 6;
+        }
+        if ( this.cw.version == Opcodes.V1_4 ) {
+            if ( (this.access & Opcodes.ACC_VARARGS) != 0 ) {
+                this.cw.newUTF8( "Varargs" );
+                size += 6;
+            }
+            if ( (this.access & Opcodes.ACC_BRIDGE) != 0 ) {
+                this.cw.newUTF8( "Bridge" );
+                size += 6;
+            }
+        }
+        if ( this.signature != null ) {
+            this.cw.newUTF8( "Signature" );
+            this.cw.newUTF8( this.signature );
+            size += 8;
+        }
+        if ( this.annd != null ) {
+            this.cw.newUTF8( "AnnotationDefault" );
+            size += 6 + this.annd.length;
+        }
+        if ( this.anns != null ) {
+            this.cw.newUTF8( "RuntimeVisibleAnnotations" );
+            size += 8 + this.anns.getSize();
+        }
+        if ( this.ianns != null ) {
+            this.cw.newUTF8( "RuntimeInvisibleAnnotations" );
+            size += 8 + this.ianns.getSize();
+        }
+        if ( this.panns != null ) {
+            this.cw.newUTF8( "RuntimeVisibleParameterAnnotations" );
+            size += 7 + 2 * this.panns.length;
+            for ( int i = this.panns.length - 1; i >= 0; --i ) {
+                size += this.panns[i] == null ? 0 : this.panns[i].getSize();
+            }
+        }
+        if ( this.ipanns != null ) {
+            this.cw.newUTF8( "RuntimeInvisibleParameterAnnotations" );
+            size += 7 + 2 * this.ipanns.length;
+            for ( int i = this.ipanns.length - 1; i >= 0; --i ) {
+                size += this.ipanns[i] == null ? 0 : this.ipanns[i].getSize();
+            }
+        }
+        if ( this.attrs != null ) {
+            size += this.attrs.getSize( this.cw,
+                                        null,
+                                        0,
+                                        -1,
+                                        -1 );
+        }
+        return size;
+    }
+
+    /**
+     * Puts the bytecode of this method in the given byte vector.
+     * 
+     * @param out the byte vector into which the bytecode of this method must be
+     *        copied.
+     */
+    final void put(final ByteVector out) {
+        out.putShort( this.access ).putShort( this.name ).putShort( this.desc );
+        if ( this.classReaderOffset != 0 ) {
+            out.putByteArray( this.cw.cr.b,
+                              this.classReaderOffset,
+                              this.classReaderLength );
+            return;
+        }
+        int attributeCount = 0;
+        if ( this.code.length > 0 ) {
+            ++attributeCount;
+        }
+        if ( this.exceptionCount > 0 ) {
+            ++attributeCount;
+        }
+        if ( (this.access & Opcodes.ACC_SYNTHETIC) != 0 && (this.cw.version & 0xffff) < Opcodes.V1_5 ) {
+            ++attributeCount;
+        }
+        if ( (this.access & Opcodes.ACC_DEPRECATED) != 0 ) {
+            ++attributeCount;
+        }
+        if ( this.cw.version == Opcodes.V1_4 ) {
+            if ( (this.access & Opcodes.ACC_VARARGS) != 0 ) {
+                ++attributeCount;
+            }
+            if ( (this.access & Opcodes.ACC_BRIDGE) != 0 ) {
+                ++attributeCount;
+            }
+        }
+        if ( this.signature != null ) {
+            ++attributeCount;
+        }
+        if ( this.annd != null ) {
+            ++attributeCount;
+        }
+        if ( this.anns != null ) {
+            ++attributeCount;
+        }
+        if ( this.ianns != null ) {
+            ++attributeCount;
+        }
+        if ( this.panns != null ) {
+            ++attributeCount;
+        }
+        if ( this.ipanns != null ) {
+            ++attributeCount;
+        }
+        if ( this.attrs != null ) {
+            attributeCount += this.attrs.getCount();
+        }
+        out.putShort( attributeCount );
+        if ( this.code.length > 0 ) {
+            int size = 12 + this.code.length + 8 * this.catchCount;
+            if ( this.localVar != null ) {
+                size += 8 + this.localVar.length;
+            }
+            if ( this.localVarType != null ) {
+                size += 8 + this.localVarType.length;
+            }
+            if ( this.lineNumber != null ) {
+                size += 8 + this.lineNumber.length;
+            }
+            if ( this.cattrs != null ) {
+                size += this.cattrs.getSize( this.cw,
+                                             this.code.data,
+                                             this.code.length,
+                                             this.maxStack,
+                                             this.maxLocals );
+            }
+            out.putShort( this.cw.newUTF8( "Code" ) ).putInt( size );
+            out.putShort( this.maxStack ).putShort( this.maxLocals );
+            out.putInt( this.code.length ).putByteArray( this.code.data,
+                                                         0,
+                                                         this.code.length );
+            out.putShort( this.catchCount );
+            if ( this.catchCount > 0 ) {
+                Handler h = this.catchTable;
+                while ( h != null ) {
+                    out.putShort( h.start.position ).putShort( h.end.position ).putShort( h.handler.position ).putShort( h.type );
+                    h = h.next;
+                }
+            }
+            attributeCount = 0;
+            if ( this.localVar != null ) {
+                ++attributeCount;
+            }
+            if ( this.localVarType != null ) {
+                ++attributeCount;
+            }
+            if ( this.lineNumber != null ) {
+                ++attributeCount;
+            }
+            if ( this.cattrs != null ) {
+                attributeCount += this.cattrs.getCount();
+            }
+            out.putShort( attributeCount );
+            if ( this.localVar != null ) {
+                out.putShort( this.cw.newUTF8( "LocalVariableTable" ) );
+                out.putInt( this.localVar.length + 2 ).putShort( this.localVarCount );
+                out.putByteArray( this.localVar.data,
+                                  0,
+                                  this.localVar.length );
+            }
+            if ( this.localVarType != null ) {
+                out.putShort( this.cw.newUTF8( "LocalVariableTypeTable" ) );
+                out.putInt( this.localVarType.length + 2 ).putShort( this.localVarTypeCount );
+                out.putByteArray( this.localVarType.data,
+                                  0,
+                                  this.localVarType.length );
+            }
+            if ( this.lineNumber != null ) {
+                out.putShort( this.cw.newUTF8( "LineNumberTable" ) );
+                out.putInt( this.lineNumber.length + 2 ).putShort( this.lineNumberCount );
+                out.putByteArray( this.lineNumber.data,
+                                  0,
+                                  this.lineNumber.length );
+            }
+            if ( this.cattrs != null ) {
+                this.cattrs.put( this.cw,
+                                 this.code.data,
+                                 this.code.length,
+                                 this.maxLocals,
+                                 this.maxStack,
+                                 out );
+            }
+        }
+        if ( this.exceptionCount > 0 ) {
+            out.putShort( this.cw.newUTF8( "Exceptions" ) ).putInt( 2 * this.exceptionCount + 2 );
+            out.putShort( this.exceptionCount );
+            for ( int i = 0; i < this.exceptionCount; ++i ) {
+                out.putShort( this.exceptions[i] );
+            }
+        }
+        if ( (this.access & Opcodes.ACC_SYNTHETIC) != 0 && (this.cw.version & 0xffff) < Opcodes.V1_5 ) {
+            out.putShort( this.cw.newUTF8( "Synthetic" ) ).putInt( 0 );
+        }
+        if ( (this.access & Opcodes.ACC_DEPRECATED) != 0 ) {
+            out.putShort( this.cw.newUTF8( "Deprecated" ) ).putInt( 0 );
+        }
+        if ( this.cw.version == Opcodes.V1_4 ) {
+            if ( (this.access & Opcodes.ACC_VARARGS) != 0 ) {
+                out.putShort( this.cw.newUTF8( "Varargs" ) ).putInt( 0 );
+            }
+            if ( (this.access & Opcodes.ACC_BRIDGE) != 0 ) {
+                out.putShort( this.cw.newUTF8( "Bridge" ) ).putInt( 0 );
+            }
+        }
+        if ( this.signature != null ) {
+            out.putShort( this.cw.newUTF8( "Signature" ) ).putInt( 2 ).putShort( this.cw.newUTF8( this.signature ) );
+        }
+        if ( this.annd != null ) {
+            out.putShort( this.cw.newUTF8( "AnnotationDefault" ) );
+            out.putInt( this.annd.length );
+            out.putByteArray( this.annd.data,
+                              0,
+                              this.annd.length );
+        }
+        if ( this.anns != null ) {
+            out.putShort( this.cw.newUTF8( "RuntimeVisibleAnnotations" ) );
+            this.anns.put( out );
+        }
+        if ( this.ianns != null ) {
+            out.putShort( this.cw.newUTF8( "RuntimeInvisibleAnnotations" ) );
+            this.ianns.put( out );
+        }
+        if ( this.panns != null ) {
+            out.putShort( this.cw.newUTF8( "RuntimeVisibleParameterAnnotations" ) );
+            AnnotationWriter.put( this.panns,
+                                  out );
+        }
+        if ( this.ipanns != null ) {
+            out.putShort( this.cw.newUTF8( "RuntimeInvisibleParameterAnnotations" ) );
+            AnnotationWriter.put( this.ipanns,
+                                  out );
+        }
+        if ( this.attrs != null ) {
+            this.attrs.put( this.cw,
+                            null,
+                            0,
+                            -1,
+                            -1,
+                            out );
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods: instruction resizing (used to handle GOTO_W and JSR_W)
+    // ------------------------------------------------------------------------
+
+    /**
+     * Resizes the designated instructions, while keeping jump offsets and
+     * instruction addresses consistent. This may require to resize other
+     * existing instructions, or even to introduce new instructions: for
+     * example, increasing the size of an instruction by 2 at the middle of a
+     * method can increases the offset of an IFEQ instruction from 32766 to
+     * 32768, in which case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W
+     * 32765. This, in turn, may require to increase the size of another jump
+     * instruction, and so on... All these operations are handled automatically
+     * by this method. <p> <i>This method must be called after all the method
+     * that is being built has been visited</i>. In particular, the
+     * {@link Label Label} objects used to construct the method are no longer
+     * valid after this method has been called.
+     * 
+     * @param indexes current positions of the instructions to be resized. Each
+     *        instruction must be designated by the index of its <i>last</i>
+     *        byte, plus one (or, in other words, by the index of the <i>first</i>
+     *        byte of the <i>next</i> instruction).
+     * @param sizes the number of bytes to be <i>added</i> to the above
+     *        instructions. More precisely, for each i &lt; <tt>len</tt>,
+     *        <tt>sizes</tt>[i] bytes will be added at the end of the
+     *        instruction designated by <tt>indexes</tt>[i] or, if
+     *        <tt>sizes</tt>[i] is negative, the <i>last</i> |<tt>sizes[i]</tt>|
+     *        bytes of the instruction will be removed (the instruction size
+     *        <i>must not</i> become negative or null). The gaps introduced by
+     *        this method must be filled in "manually" in {@link #code code}
+     *        method.
+     * @param len the number of instruction to be resized. Must be smaller than
+     *        or equal to <tt>indexes</tt>.length and <tt>sizes</tt>.length.
+     * @return the <tt>indexes</tt> array, which now contains the new
+     *         positions of the resized instructions (designated as above).
+     */
+    private int[] resizeInstructions(final int[] indexes,
+                                     final int[] sizes,
+                                     final int len) {
+        byte[] b = this.code.data; // bytecode of the method
+        int u, v, label; // indexes in b
+        int i, j; // loop indexes
+
+        /*
+         * 1st step: As explained above, resizing an instruction may require to
+         * resize another one, which may require to resize yet another one, and
+         * so on. The first step of the algorithm consists in finding all the
+         * instructions that need to be resized, without modifying the code.
+         * This is done by the following "fix point" algorithm:
+         * 
+         * Parse the code to find the jump instructions whose offset will need
+         * more than 2 bytes to be stored (the future offset is computed from
+         * the current offset and from the number of bytes that will be inserted
+         * or removed between the source and target instructions). For each such
+         * instruction, adds an entry in (a copy of) the indexes and sizes
+         * arrays (if this has not already been done in a previous iteration!).
+         * 
+         * If at least one entry has been added during the previous step, go
+         * back to the beginning, otherwise stop.
+         * 
+         * In fact the real algorithm is complicated by the fact that the size
+         * of TABLESWITCH and LOOKUPSWITCH instructions depends on their
+         * position in the bytecode (because of padding). In order to ensure the
+         * convergence of the algorithm, the number of bytes to be added or
+         * removed from these instructions is over estimated during the previous
+         * loop, and computed exactly only after the loop is finished (this
+         * requires another pass to parse the bytecode of the method).
+         */
+        int[] allIndexes = new int[len]; // copy of indexes
+        int[] allSizes = new int[len]; // copy of sizes
+        boolean[] resize; // instructions to be resized
+        int newOffset; // future offset of a jump instruction
+
+        System.arraycopy( indexes,
+                          0,
+                          allIndexes,
+                          0,
+                          len );
+        System.arraycopy( sizes,
+                          0,
+                          allSizes,
+                          0,
+                          len );
+        resize = new boolean[this.code.length];
+
+        // 3 = loop again, 2 = loop ended, 1 = last pass, 0 = done
+        int state = 3;
+        do {
+            if ( state == 3 ) {
+                state = 2;
+            }
+            u = 0;
+            while ( u < b.length ) {
+                int opcode = b[u] & 0xFF; // opcode of current instruction
+                int insert = 0; // bytes to be added after this instruction
+
+                switch ( ClassWriter.TYPE[opcode] ) {
+                    case ClassWriter.NOARG_INSN :
+                    case ClassWriter.IMPLVAR_INSN :
+                        u += 1;
+                        break;
+                    case ClassWriter.LABEL_INSN :
+                        if ( opcode > 201 ) {
+                            // converts temporary opcodes 202 to 217, 218 and
+                            // 219 to IFEQ ... JSR (inclusive), IFNULL and
+                            // IFNONNULL
+                            opcode = opcode < 218 ? opcode - 49 : opcode - 20;
+                            label = u + readUnsignedShort( b,
+                                                           u + 1 );
+                        } else {
+                            label = u + readShort( b,
+                                                   u + 1 );
+                        }
+                        newOffset = getNewOffset( allIndexes,
+                                                  allSizes,
+                                                  u,
+                                                  label );
+                        if ( newOffset < Short.MIN_VALUE || newOffset > Short.MAX_VALUE ) {
+                            if ( !resize[u] ) {
+                                if ( opcode == Opcodes.GOTO || opcode == Opcodes.JSR ) {
+                                    // two additional bytes will be required to
+                                    // replace this GOTO or JSR instruction with
+                                    // a GOTO_W or a JSR_W
+                                    insert = 2;
+                                } else {
+                                    // five additional bytes will be required to
+                                    // replace this IFxxx <l> instruction with
+                                    // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx
+                                    // is the "opposite" opcode of IFxxx (i.e.,
+                                    // IFNE for IFEQ) and where <l'> designates
+                                    // the instruction just after the GOTO_W.
+                                    insert = 5;
+                                }
+                                resize[u] = true;
+                            }
+                        }
+                        u += 3;
+                        break;
+                    case ClassWriter.LABELW_INSN :
+                        u += 5;
+                        break;
+                    case ClassWriter.TABL_INSN :
+                        if ( state == 1 ) {
+                            // true number of bytes to be added (or removed)
+                            // from this instruction = (future number of padding
+                            // bytes - current number of padding byte) -
+                            // previously over estimated variation =
+                            // = ((3 - newOffset%4) - (3 - u%4)) - u%4
+                            // = (-newOffset%4 + u%4) - u%4
+                            // = -(newOffset & 3)
+                            newOffset = getNewOffset( allIndexes,
+                                                      allSizes,
+                                                      0,
+                                                      u );
+                            insert = -(newOffset & 3);
+                        } else if ( !resize[u] ) {
+                            // over estimation of the number of bytes to be
+                            // added to this instruction = 3 - current number
+                            // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3
+                            insert = u & 3;
+                            resize[u] = true;
+                        }
+                        // skips instruction
+                        u = u + 4 - (u & 3);
+                        u += 4 * (readInt( b,
+                                           u + 8 ) - readInt( b,
+                                                              u + 4 ) + 1) + 12;
+                        break;
+                    case ClassWriter.LOOK_INSN :
+                        if ( state == 1 ) {
+                            // like TABL_INSN
+                            newOffset = getNewOffset( allIndexes,
+                                                      allSizes,
+                                                      0,
+                                                      u );
+                            insert = -(newOffset & 3);
+                        } else if ( !resize[u] ) {
+                            // like TABL_INSN
+                            insert = u & 3;
+                            resize[u] = true;
+                        }
+                        // skips instruction
+                        u = u + 4 - (u & 3);
+                        u += 8 * readInt( b,
+                                          u + 4 ) + 8;
+                        break;
+                    case ClassWriter.WIDE_INSN :
+                        opcode = b[u + 1] & 0xFF;
+                        if ( opcode == Opcodes.IINC ) {
+                            u += 6;
+                        } else {
+                            u += 4;
+                        }
+                        break;
+                    case ClassWriter.VAR_INSN :
+                    case ClassWriter.SBYTE_INSN :
+                    case ClassWriter.LDC_INSN :
+                        u += 2;
+                        break;
+                    case ClassWriter.SHORT_INSN :
+                    case ClassWriter.LDCW_INSN :
+                    case ClassWriter.FIELDORMETH_INSN :
+                    case ClassWriter.TYPE_INSN :
+                    case ClassWriter.IINC_INSN :
+                        u += 3;
+                        break;
+                    case ClassWriter.ITFMETH_INSN :
+                        u += 5;
+                        break;
+                    // case ClassWriter.MANA_INSN:
+                    default :
+                        u += 4;
+                        break;
+                }
+                if ( insert != 0 ) {
+                    // adds a new (u, insert) entry in the allIndexes and
+                    // allSizes arrays
+                    final int[] newIndexes = new int[allIndexes.length + 1];
+                    final int[] newSizes = new int[allSizes.length + 1];
+                    System.arraycopy( allIndexes,
+                                      0,
+                                      newIndexes,
+                                      0,
+                                      allIndexes.length );
+                    System.arraycopy( allSizes,
+                                      0,
+                                      newSizes,
+                                      0,
+                                      allSizes.length );
+                    newIndexes[allIndexes.length] = u;
+                    newSizes[allSizes.length] = insert;
+                    allIndexes = newIndexes;
+                    allSizes = newSizes;
+                    if ( insert > 0 ) {
+                        state = 3;
+                    }
+                }
+            }
+            if ( state < 3 ) {
+                --state;
+            }
+        } while ( state != 0 );
+
+        // 2nd step:
+        // copies the bytecode of the method into a new bytevector, updates the
+        // offsets, and inserts (or removes) bytes as requested.
+
+        final ByteVector newCode = new ByteVector( this.code.length );
+
+        u = 0;
+        while ( u < this.code.length ) {
+            for ( i = allIndexes.length - 1; i >= 0; --i ) {
+                if ( allIndexes[i] == u ) {
+                    if ( i < len ) {
+                        if ( sizes[i] > 0 ) {
+                            newCode.putByteArray( null,
+                                                  0,
+                                                  sizes[i] );
+                        } else {
+                            newCode.length += sizes[i];
+                        }
+                        indexes[i] = newCode.length;
+                    }
+                }
+            }
+            int opcode = b[u] & 0xFF;
+            switch ( ClassWriter.TYPE[opcode] ) {
+                case ClassWriter.NOARG_INSN :
+                case ClassWriter.IMPLVAR_INSN :
+                    newCode.putByte( opcode );
+                    u += 1;
+                    break;
+                case ClassWriter.LABEL_INSN :
+                    if ( opcode > 201 ) {
+                        // changes temporary opcodes 202 to 217 (inclusive), 218
+                        // and 219 to IFEQ ... JSR (inclusive), IFNULL and
+                        // IFNONNULL
+                        opcode = opcode < 218 ? opcode - 49 : opcode - 20;
+                        label = u + readUnsignedShort( b,
+                                                       u + 1 );
+                    } else {
+                        label = u + readShort( b,
+                                               u + 1 );
+                    }
+                    newOffset = getNewOffset( allIndexes,
+                                              allSizes,
+                                              u,
+                                              label );
+                    if ( resize[u] ) {
+                        // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
+                        // <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is
+                        // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
+                        // and where <l'> designates the instruction just after
+                        // the GOTO_W.
+                        if ( opcode == Opcodes.GOTO ) {
+                            newCode.putByte( 200 ); // GOTO_W
+                        } else if ( opcode == Opcodes.JSR ) {
+                            newCode.putByte( 201 ); // JSR_W
+                        } else {
+                            newCode.putByte( opcode <= 166 ? ((opcode + 1) ^ 1) - 1 : opcode ^ 1 );
+                            newCode.putShort( 8 ); // jump offset
+                            newCode.putByte( 200 ); // GOTO_W
+                            // newOffset now computed from start of GOTO_W
+                            newOffset -= 3;
+                        }
+                        newCode.putInt( newOffset );
+                    } else {
+                        newCode.putByte( opcode );
+                        newCode.putShort( newOffset );
+                    }
+                    u += 3;
+                    break;
+                case ClassWriter.LABELW_INSN :
+                    label = u + readInt( b,
+                                         u + 1 );
+                    newOffset = getNewOffset( allIndexes,
+                                              allSizes,
+                                              u,
+                                              label );
+                    newCode.putByte( opcode );
+                    newCode.putInt( newOffset );
+                    u += 5;
+                    break;
+                case ClassWriter.TABL_INSN :
+                    // skips 0 to 3 padding bytes
+                    v = u;
+                    u = u + 4 - (v & 3);
+                    // reads and copies instruction
+                    newCode.putByte( Opcodes.TABLESWITCH );
+                    while ( newCode.length % 4 != 0 ) {
+                        newCode.putByte( 0 );
+                    }
+                    label = v + readInt( b,
+                                         u );
+                    u += 4;
+                    newOffset = getNewOffset( allIndexes,
+                                              allSizes,
+                                              v,
+                                              label );
+                    newCode.putInt( newOffset );
+                    j = readInt( b,
+                                 u );
+                    u += 4;
+                    newCode.putInt( j );
+                    j = readInt( b,
+                                 u ) - j + 1;
+                    u += 4;
+                    newCode.putInt( readInt( b,
+                                             u - 4 ) );
+                    for ( ; j > 0; --j ) {
+                        label = v + readInt( b,
+                                             u );
+                        u += 4;
+                        newOffset = getNewOffset( allIndexes,
+                                                  allSizes,
+                                                  v,
+                                                  label );
+                        newCode.putInt( newOffset );
+                    }
+                    break;
+                case ClassWriter.LOOK_INSN :
+                    // skips 0 to 3 padding bytes
+                    v = u;
+                    u = u + 4 - (v & 3);
+                    // reads and copies instruction
+                    newCode.putByte( Opcodes.LOOKUPSWITCH );
+                    while ( newCode.length % 4 != 0 ) {
+                        newCode.putByte( 0 );
+                    }
+                    label = v + readInt( b,
+                                         u );
+                    u += 4;
+                    newOffset = getNewOffset( allIndexes,
+                                              allSizes,
+                                              v,
+                                              label );
+                    newCode.putInt( newOffset );
+                    j = readInt( b,
+                                 u );
+                    u += 4;
+                    newCode.putInt( j );
+                    for ( ; j > 0; --j ) {
+                        newCode.putInt( readInt( b,
+                                                 u ) );
+                        u += 4;
+                        label = v + readInt( b,
+                                             u );
+                        u += 4;
+                        newOffset = getNewOffset( allIndexes,
+                                                  allSizes,
+                                                  v,
+                                                  label );
+                        newCode.putInt( newOffset );
+                    }
+                    break;
+                case ClassWriter.WIDE_INSN :
+                    opcode = b[u + 1] & 0xFF;
+                    if ( opcode == Opcodes.IINC ) {
+                        newCode.putByteArray( b,
+                                              u,
+                                              6 );
+                        u += 6;
+                    } else {
+                        newCode.putByteArray( b,
+                                              u,
+                                              4 );
+                        u += 4;
+                    }
+                    break;
+                case ClassWriter.VAR_INSN :
+                case ClassWriter.SBYTE_INSN :
+                case ClassWriter.LDC_INSN :
+                    newCode.putByteArray( b,
+                                          u,
+                                          2 );
+                    u += 2;
+                    break;
+                case ClassWriter.SHORT_INSN :
+                case ClassWriter.LDCW_INSN :
+                case ClassWriter.FIELDORMETH_INSN :
+                case ClassWriter.TYPE_INSN :
+                case ClassWriter.IINC_INSN :
+                    newCode.putByteArray( b,
+                                          u,
+                                          3 );
+                    u += 3;
+                    break;
+                case ClassWriter.ITFMETH_INSN :
+                    newCode.putByteArray( b,
+                                          u,
+                                          5 );
+                    u += 5;
+                    break;
+                // case MANA_INSN:
+                default :
+                    newCode.putByteArray( b,
+                                          u,
+                                          4 );
+                    u += 4;
+                    break;
+            }
+        }
+
+        // updates the exception handler block labels
+        Handler h = this.catchTable;
+        while ( h != null ) {
+            getNewOffset( allIndexes,
+                          allSizes,
+                          h.start );
+            getNewOffset( allIndexes,
+                          allSizes,
+                          h.end );
+            getNewOffset( allIndexes,
+                          allSizes,
+                          h.handler );
+            h = h.next;
+        }
+        for ( i = 0; i < 2; ++i ) {
+            final ByteVector bv = i == 0 ? this.localVar : this.localVarType;
+            if ( bv != null ) {
+                b = bv.data;
+                u = 0;
+                while ( u < bv.length ) {
+                    label = readUnsignedShort( b,
+                                               u );
+                    newOffset = getNewOffset( allIndexes,
+                                              allSizes,
+                                              0,
+                                              label );
+                    writeShort( b,
+                                u,
+                                newOffset );
+                    label += readUnsignedShort( b,
+                                                u + 2 );
+                    newOffset = getNewOffset( allIndexes,
+                                              allSizes,
+                                              0,
+                                              label ) - newOffset;
+                    writeShort( b,
+                                u + 2,
+                                newOffset );
+                    u += 10;
+                }
+            }
+        }
+        if ( this.lineNumber != null ) {
+            b = this.lineNumber.data;
+            u = 0;
+            while ( u < this.lineNumber.length ) {
+                writeShort( b,
+                            u,
+                            getNewOffset( allIndexes,
+                                          allSizes,
+                                          0,
+                                          readUnsignedShort( b,
+                                                             u ) ) );
+                u += 4;
+            }
+        }
+        // updates the labels of the other attributes
+        while ( this.cattrs != null ) {
+            final Label[] labels = this.cattrs.getLabels();
+            if ( labels != null ) {
+                for ( i = labels.length - 1; i >= 0; --i ) {
+                    if ( !labels[i].resized ) {
+                        labels[i].position = getNewOffset( allIndexes,
+                                                           allSizes,
+                                                           0,
+                                                           labels[i].position );
+                        labels[i].resized = true;
+                    }
+                }
+            }
+        }
+
+        // replaces old bytecodes with new ones
+        this.code = newCode;
+
+        // returns the positions of the resized instructions
+        return indexes;
+    }
+
+    /**
+     * Reads an unsigned short value in the given byte array.
+     * 
+     * @param b a byte array.
+     * @param index the start index of the value to be read.
+     * @return the read value.
+     */
+    static int readUnsignedShort(final byte[] b,
+                                 final int index) {
+        return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
+    }
+
+    /**
+     * Reads a signed short value in the given byte array.
+     * 
+     * @param b a byte array.
+     * @param index the start index of the value to be read.
+     * @return the read value.
+     */
+    static short readShort(final byte[] b,
+                           final int index) {
+        return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
+    }
+
+    /**
+     * Reads a signed int value in the given byte array.
+     * 
+     * @param b a byte array.
+     * @param index the start index of the value to be read.
+     * @return the read value.
+     */
+    static int readInt(final byte[] b,
+                       final int index) {
+        return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16) | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
+    }
+
+    /**
+     * Writes a short value in the given byte array.
+     * 
+     * @param b a byte array.
+     * @param index where the first byte of the short value must be written.
+     * @param s the value to be written in the given byte array.
+     */
+    static void writeShort(final byte[] b,
+                           final int index,
+                           final int s) {
+        b[index] = (byte) (s >>> 8);
+        b[index + 1] = (byte) s;
+    }
+
+    /**
+     * Computes the future value of a bytecode offset. <p> Note: it is possible
+     * to have several entries for the same instruction in the <tt>indexes</tt>
+     * and <tt>sizes</tt>: two entries (index=a,size=b) and (index=a,size=b')
+     * are equivalent to a single entry (index=a,size=b+b').
+     * 
+     * @param indexes current positions of the instructions to be resized. Each
+     *        instruction must be designated by the index of its <i>last</i>
+     *        byte, plus one (or, in other words, by the index of the <i>first</i>
+     *        byte of the <i>next</i> instruction).
+     * @param sizes the number of bytes to be <i>added</i> to the above
+     *        instructions. More precisely, for each i < <tt>len</tt>,
+     *        <tt>sizes</tt>[i] bytes will be added at the end of the
+     *        instruction designated by <tt>indexes</tt>[i] or, if
+     *        <tt>sizes</tt>[i] is negative, the <i>last</i> |<tt>sizes[i]</tt>|
+     *        bytes of the instruction will be removed (the instruction size
+     *        <i>must not</i> become negative or null).
+     * @param begin index of the first byte of the source instruction.
+     * @param end index of the first byte of the target instruction.
+     * @return the future value of the given bytecode offset.
+     */
+    static int getNewOffset(final int[] indexes,
+                            final int[] sizes,
+                            final int begin,
+                            final int end) {
+        int offset = end - begin;
+        for ( int i = 0; i < indexes.length; ++i ) {
+            if ( begin < indexes[i] && indexes[i] <= end ) {
+                // forward jump
+                offset += sizes[i];
+            } else if ( end < indexes[i] && indexes[i] <= begin ) {
+                // backward jump
+                offset -= sizes[i];
+            }
+        }
+        return offset;
+    }
+
+    /**
+     * Updates the offset of the given label.
+     * 
+     * @param indexes current positions of the instructions to be resized. Each
+     *        instruction must be designated by the index of its <i>last</i>
+     *        byte, plus one (or, in other words, by the index of the <i>first</i>
+     *        byte of the <i>next</i> instruction).
+     * @param sizes the number of bytes to be <i>added</i> to the above
+     *        instructions. More precisely, for each i < <tt>len</tt>,
+     *        <tt>sizes</tt>[i] bytes will be added at the end of the
+     *        instruction designated by <tt>indexes</tt>[i] or, if
+     *        <tt>sizes</tt>[i] is negative, the <i>last</i> |<tt>sizes[i]</tt>|
+     *        bytes of the instruction will be removed (the instruction size
+     *        <i>must not</i> become negative or null).
+     * @param label the label whose offset must be updated.
+     */
+    static void getNewOffset(final int[] indexes,
+                             final int[] sizes,
+                             final Label label) {
+        if ( !label.resized ) {
+            label.position = getNewOffset( indexes,
+                                           sizes,
+                                           0,
+                                           label.position );
+            label.resized = true;
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Opcodes.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Opcodes.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Opcodes.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,295 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm;
+
+/**
+ * Defines the JVM opcodes, access flags and array type codes. This interface
+ * does not define all the JVM opcodes because some opcodes are automatically
+ * handled. For example, the xLOAD and xSTORE opcodes are automatically replaced
+ * by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n
+ * opcodes are therefore not defined in this interface. Likewise for LDC,
+ * automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and
+ * JSR_W.
+ * 
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public interface Opcodes {
+
+    // versions
+
+    int V1_1             = 3 << 16 | 45;
+    int V1_2             = 0 << 16 | 46;
+    int V1_3             = 0 << 16 | 47;
+    int V1_4             = 0 << 16 | 48;
+    int V1_5             = 0 << 16 | 49;
+    int V1_6             = 0 << 16 | 50;
+
+    // access flags
+
+    int ACC_PUBLIC       = 0x0001;      // class, field, method
+    int ACC_PRIVATE      = 0x0002;      // class, field, method
+    int ACC_PROTECTED    = 0x0004;      // class, field, method
+    int ACC_STATIC       = 0x0008;      // field, method
+    int ACC_FINAL        = 0x0010;      // class, field, method
+    int ACC_SUPER        = 0x0020;      // class
+    int ACC_SYNCHRONIZED = 0x0020;      // method
+    int ACC_VOLATILE     = 0x0040;      // field
+    int ACC_BRIDGE       = 0x0040;      // method
+    int ACC_VARARGS      = 0x0080;      // method
+    int ACC_TRANSIENT    = 0x0080;      // field
+    int ACC_NATIVE       = 0x0100;      // method
+    int ACC_INTERFACE    = 0x0200;      // class
+    int ACC_ABSTRACT     = 0x0400;      // class, method
+    int ACC_STRICT       = 0x0800;      // method
+    int ACC_SYNTHETIC    = 0x1000;      // class, field, method
+    int ACC_ANNOTATION   = 0x2000;      // class
+    int ACC_ENUM         = 0x4000;      // class(?) field inner
+
+    // ASM specific pseudo access flags
+
+    int ACC_DEPRECATED   = 131072;      // class, field, method
+
+    // types for NEWARRAY
+
+    int T_BOOLEAN        = 4;
+    int T_CHAR           = 5;
+    int T_FLOAT          = 6;
+    int T_DOUBLE         = 7;
+    int T_BYTE           = 8;
+    int T_SHORT          = 9;
+    int T_INT            = 10;
+    int T_LONG           = 11;
+
+    // opcodes // visit method (- = idem)
+
+    int NOP              = 0;           // visitInsn
+    int ACONST_NULL      = 1;           // -
+    int ICONST_M1        = 2;           // -
+    int ICONST_0         = 3;           // -
+    int ICONST_1         = 4;           // -
+    int ICONST_2         = 5;           // -
+    int ICONST_3         = 6;           // -
+    int ICONST_4         = 7;           // -
+    int ICONST_5         = 8;           // -
+    int LCONST_0         = 9;           // -
+    int LCONST_1         = 10;          // -
+    int FCONST_0         = 11;          // -
+    int FCONST_1         = 12;          // -
+    int FCONST_2         = 13;          // -
+    int DCONST_0         = 14;          // -
+    int DCONST_1         = 15;          // -
+    int BIPUSH           = 16;          // visitIntInsn
+    int SIPUSH           = 17;          // -
+    int LDC              = 18;          // visitLdcInsn
+    // int LDC_W = 19; // -
+    // int LDC2_W = 20; // -
+    int ILOAD            = 21;          // visitVarInsn
+    int LLOAD            = 22;          // -
+    int FLOAD            = 23;          // -
+    int DLOAD            = 24;          // -
+    int ALOAD            = 25;          // -
+    // int ILOAD_0 = 26; // -
+    // int ILOAD_1 = 27; // -
+    // int ILOAD_2 = 28; // -
+    // int ILOAD_3 = 29; // -
+    // int LLOAD_0 = 30; // -
+    // int LLOAD_1 = 31; // -
+    // int LLOAD_2 = 32; // -
+    // int LLOAD_3 = 33; // -
+    // int FLOAD_0 = 34; // -
+    // int FLOAD_1 = 35; // -
+    // int FLOAD_2 = 36; // -
+    // int FLOAD_3 = 37; // -
+    // int DLOAD_0 = 38; // -
+    // int DLOAD_1 = 39; // -
+    // int DLOAD_2 = 40; // -
+    // int DLOAD_3 = 41; // -
+    // int ALOAD_0 = 42; // -
+    // int ALOAD_1 = 43; // -
+    // int ALOAD_2 = 44; // -
+    // int ALOAD_3 = 45; // -
+    int IALOAD           = 46;          // visitInsn
+    int LALOAD           = 47;          // -
+    int FALOAD           = 48;          // -
+    int DALOAD           = 49;          // -
+    int AALOAD           = 50;          // -
+    int BALOAD           = 51;          // -
+    int CALOAD           = 52;          // -
+    int SALOAD           = 53;          // -
+    int ISTORE           = 54;          // visitVarInsn
+    int LSTORE           = 55;          // -
+    int FSTORE           = 56;          // -
+    int DSTORE           = 57;          // -
+    int ASTORE           = 58;          // -
+    // int ISTORE_0 = 59; // -
+    // int ISTORE_1 = 60; // -
+    // int ISTORE_2 = 61; // -
+    // int ISTORE_3 = 62; // -
+    // int LSTORE_0 = 63; // -
+    // int LSTORE_1 = 64; // -
+    // int LSTORE_2 = 65; // -
+    // int LSTORE_3 = 66; // -
+    // int FSTORE_0 = 67; // -
+    // int FSTORE_1 = 68; // -
+    // int FSTORE_2 = 69; // -
+    // int FSTORE_3 = 70; // -
+    // int DSTORE_0 = 71; // -
+    // int DSTORE_1 = 72; // -
+    // int DSTORE_2 = 73; // -
+    // int DSTORE_3 = 74; // -
+    // int ASTORE_0 = 75; // -
+    // int ASTORE_1 = 76; // -
+    // int ASTORE_2 = 77; // -
+    // int ASTORE_3 = 78; // -
+    int IASTORE          = 79;          // visitInsn
+    int LASTORE          = 80;          // -
+    int FASTORE          = 81;          // -
+    int DASTORE          = 82;          // -
+    int AASTORE          = 83;          // -
+    int BASTORE          = 84;          // -
+    int CASTORE          = 85;          // -
+    int SASTORE          = 86;          // -
+    int POP              = 87;          // -
+    int POP2             = 88;          // -
+    int DUP              = 89;          // -
+    int DUP_X1           = 90;          // -
+    int DUP_X2           = 91;          // -
+    int DUP2             = 92;          // -
+    int DUP2_X1          = 93;          // -
+    int DUP2_X2          = 94;          // -
+    int SWAP             = 95;          // -
+    int IADD             = 96;          // -
+    int LADD             = 97;          // -
+    int FADD             = 98;          // -
+    int DADD             = 99;          // -
+    int ISUB             = 100;         // -
+    int LSUB             = 101;         // -
+    int FSUB             = 102;         // -
+    int DSUB             = 103;         // -
+    int IMUL             = 104;         // -
+    int LMUL             = 105;         // -
+    int FMUL             = 106;         // -
+    int DMUL             = 107;         // -
+    int IDIV             = 108;         // -
+    int LDIV             = 109;         // -
+    int FDIV             = 110;         // -
+    int DDIV             = 111;         // -
+    int IREM             = 112;         // -
+    int LREM             = 113;         // -
+    int FREM             = 114;         // -
+    int DREM             = 115;         // -
+    int INEG             = 116;         // -
+    int LNEG             = 117;         // -
+    int FNEG             = 118;         // -
+    int DNEG             = 119;         // -
+    int ISHL             = 120;         // -
+    int LSHL             = 121;         // -
+    int ISHR             = 122;         // -
+    int LSHR             = 123;         // -
+    int IUSHR            = 124;         // -
+    int LUSHR            = 125;         // -
+    int IAND             = 126;         // -
+    int LAND             = 127;         // -
+    int IOR              = 128;         // -
+    int LOR              = 129;         // -
+    int IXOR             = 130;         // -
+    int LXOR             = 131;         // -
+    int IINC             = 132;         // visitIincInsn
+    int I2L              = 133;         // visitInsn
+    int I2F              = 134;         // -
+    int I2D              = 135;         // -
+    int L2I              = 136;         // -
+    int L2F              = 137;         // -
+    int L2D              = 138;         // -
+    int F2I              = 139;         // -
+    int F2L              = 140;         // -
+    int F2D              = 141;         // -
+    int D2I              = 142;         // -
+    int D2L              = 143;         // -
+    int D2F              = 144;         // -
+    int I2B              = 145;         // -
+    int I2C              = 146;         // -
+    int I2S              = 147;         // -
+    int LCMP             = 148;         // -
+    int FCMPL            = 149;         // -
+    int FCMPG            = 150;         // -
+    int DCMPL            = 151;         // -
+    int DCMPG            = 152;         // -
+    int IFEQ             = 153;         // visitJumpInsn
+    int IFNE             = 154;         // -
+    int IFLT             = 155;         // -
+    int IFGE             = 156;         // -
+    int IFGT             = 157;         // -
+    int IFLE             = 158;         // -
+    int IF_ICMPEQ        = 159;         // -
+    int IF_ICMPNE        = 160;         // -
+    int IF_ICMPLT        = 161;         // -
+    int IF_ICMPGE        = 162;         // -
+    int IF_ICMPGT        = 163;         // -
+    int IF_ICMPLE        = 164;         // -
+    int IF_ACMPEQ        = 165;         // -
+    int IF_ACMPNE        = 166;         // -
+    int GOTO             = 167;         // -
+    int JSR              = 168;         // -
+    int RET              = 169;         // visitVarInsn
+    int TABLESWITCH      = 170;         // visiTableSwitchInsn
+    int LOOKUPSWITCH     = 171;         // visitLookupSwitch
+    int IRETURN          = 172;         // visitInsn
+    int LRETURN          = 173;         // -
+    int FRETURN          = 174;         // -
+    int DRETURN          = 175;         // -
+    int ARETURN          = 176;         // -
+    int RETURN           = 177;         // -
+    int GETSTATIC        = 178;         // visitFieldInsn
+    int PUTSTATIC        = 179;         // -
+    int GETFIELD         = 180;         // -
+    int PUTFIELD         = 181;         // -
+    int INVOKEVIRTUAL    = 182;         // visitMethodInsn
+    int INVOKESPECIAL    = 183;         // -
+    int INVOKESTATIC     = 184;         // -
+    int INVOKEINTERFACE  = 185;         // -
+    // int UNUSED = 186; // NOT VISITED
+    int NEW              = 187;         // visitTypeInsn
+    int NEWARRAY         = 188;         // visitIntInsn
+    int ANEWARRAY        = 189;         // visitTypeInsn
+    int ARRAYLENGTH      = 190;         // visitInsn
+    int ATHROW           = 191;         // -
+    int CHECKCAST        = 192;         // visitTypeInsn
+    int INSTANCEOF       = 193;         // -
+    int MONITORENTER     = 194;         // visitInsn
+    int MONITOREXIT      = 195;         // -
+    // int WIDE = 196; // NOT VISITED
+    int MULTIANEWARRAY   = 197;         // visitMultiANewArrayInsn
+    int IFNULL           = 198;         // visitJumpInsn
+    int IFNONNULL        = 199;         // -
+    // int GOTO_W = 200; // -
+    // int JSR_W = 201; // -
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Type.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Type.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/Type.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,783 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm;
+
+import java.lang.reflect.Method;
+
+/**
+ * A Java type. This class can be used to make it easier to manipulate type and
+ * method descriptors.
+ * 
+ * @author Eric Bruneton
+ * @author Chris Nokleberg
+ */
+public class Type {
+
+    /**
+     * The sort of the <tt>void</tt> type. See {@link #getSort getSort}.
+     */
+    public final static int  VOID         = 0;
+
+    /**
+     * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}.
+     */
+    public final static int  BOOLEAN      = 1;
+
+    /**
+     * The sort of the <tt>char</tt> type. See {@link #getSort getSort}.
+     */
+    public final static int  CHAR         = 2;
+
+    /**
+     * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}.
+     */
+    public final static int  BYTE         = 3;
+
+    /**
+     * The sort of the <tt>short</tt> type. See {@link #getSort getSort}.
+     */
+    public final static int  SHORT        = 4;
+
+    /**
+     * The sort of the <tt>int</tt> type. See {@link #getSort getSort}.
+     */
+    public final static int  INT          = 5;
+
+    /**
+     * The sort of the <tt>float</tt> type. See {@link #getSort getSort}.
+     */
+    public final static int  FLOAT        = 6;
+
+    /**
+     * The sort of the <tt>long</tt> type. See {@link #getSort getSort}.
+     */
+    public final static int  LONG         = 7;
+
+    /**
+     * The sort of the <tt>double</tt> type. See {@link #getSort getSort}.
+     */
+    public final static int  DOUBLE       = 8;
+
+    /**
+     * The sort of array reference types. See {@link #getSort getSort}.
+     */
+    public final static int  ARRAY        = 9;
+
+    /**
+     * The sort of object reference type. See {@link #getSort getSort}.
+     */
+    public final static int  OBJECT       = 10;
+
+    /**
+     * The <tt>void</tt> type.
+     */
+    public final static Type VOID_TYPE    = new Type( Type.VOID );
+
+    /**
+     * The <tt>boolean</tt> type.
+     */
+    public final static Type BOOLEAN_TYPE = new Type( Type.BOOLEAN );
+
+    /**
+     * The <tt>char</tt> type.
+     */
+    public final static Type CHAR_TYPE    = new Type( Type.CHAR );
+
+    /**
+     * The <tt>byte</tt> type.
+     */
+    public final static Type BYTE_TYPE    = new Type( Type.BYTE );
+
+    /**
+     * The <tt>short</tt> type.
+     */
+    public final static Type SHORT_TYPE   = new Type( Type.SHORT );
+
+    /**
+     * The <tt>int</tt> type.
+     */
+    public final static Type INT_TYPE     = new Type( Type.INT );
+
+    /**
+     * The <tt>float</tt> type.
+     */
+    public final static Type FLOAT_TYPE   = new Type( Type.FLOAT );
+
+    /**
+     * The <tt>long</tt> type.
+     */
+    public final static Type LONG_TYPE    = new Type( Type.LONG );
+
+    /**
+     * The <tt>double</tt> type.
+     */
+    public final static Type DOUBLE_TYPE  = new Type( Type.DOUBLE );
+
+    // ------------------------------------------------------------------------
+    // Fields
+    // ------------------------------------------------------------------------
+
+    /**
+     * The sort of this Java type.
+     */
+    private final int        sort;
+
+    /**
+     * A buffer containing the descriptor of this Java type. This field is only
+     * used for reference types.
+     */
+    private char[]           buf;
+
+    /**
+     * The offset of the descriptor of this Java type in {@link #buf buf}. This
+     * field is only used for reference types.
+     */
+    private int              off;
+
+    /**
+     * The length of the descriptor of this Java type.
+     */
+    private int              len;
+
+    // ------------------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------------------
+
+    /**
+     * Constructs a primitive type.
+     * 
+     * @param sort the sort of the primitive type to be constructed.
+     */
+    private Type(final int sort) {
+        this.sort = sort;
+        this.len = 1;
+    }
+
+    /**
+     * Constructs a reference type.
+     * 
+     * @param sort the sort of the reference type to be constructed.
+     * @param buf a buffer containing the descriptor of the previous type.
+     * @param off the offset of this descriptor in the previous buffer.
+     * @param len the length of this descriptor.
+     */
+    private Type(final int sort,
+                 final char[] buf,
+                 final int off,
+                 final int len) {
+        this.sort = sort;
+        this.buf = buf;
+        this.off = off;
+        this.len = len;
+    }
+
+    /**
+     * Returns the Java type corresponding to the given type descriptor.
+     * 
+     * @param typeDescriptor a type descriptor.
+     * @return the Java type corresponding to the given type descriptor.
+     */
+    public static Type getType(final String typeDescriptor) {
+        return getType( typeDescriptor.toCharArray(),
+                        0 );
+    }
+
+    /**
+     * Returns the Java type corresponding to the given class.
+     * 
+     * @param c a class.
+     * @return the Java type corresponding to the given class.
+     */
+    public static Type getType(final Class c) {
+        if ( c.isPrimitive() ) {
+            if ( c == Integer.TYPE ) {
+                return Type.INT_TYPE;
+            } else if ( c == Void.TYPE ) {
+                return Type.VOID_TYPE;
+            } else if ( c == Boolean.TYPE ) {
+                return Type.BOOLEAN_TYPE;
+            } else if ( c == Byte.TYPE ) {
+                return Type.BYTE_TYPE;
+            } else if ( c == Character.TYPE ) {
+                return Type.CHAR_TYPE;
+            } else if ( c == Short.TYPE ) {
+                return Type.SHORT_TYPE;
+            } else if ( c == Double.TYPE ) {
+                return Type.DOUBLE_TYPE;
+            } else if ( c == Float.TYPE ) {
+                return Type.FLOAT_TYPE;
+            } else /* if (c == Long.TYPE) */{
+                return Type.LONG_TYPE;
+            }
+        } else {
+            return getType( getDescriptor( c ) );
+        }
+    }
+
+    /**
+     * Returns the Java types corresponding to the argument types of the given
+     * method descriptor.
+     * 
+     * @param methodDescriptor a method descriptor.
+     * @return the Java types corresponding to the argument types of the given
+     *         method descriptor.
+     */
+    public static Type[] getArgumentTypes(final String methodDescriptor) {
+        final char[] buf = methodDescriptor.toCharArray();
+        int off = 1;
+        int size = 0;
+        while ( true ) {
+            final char car = buf[off++];
+            if ( car == ')' ) {
+                break;
+            } else if ( car == 'L' ) {
+                while ( buf[off++] != ';' ) {
+                }
+                ++size;
+            } else if ( car != '[' ) {
+                ++size;
+            }
+        }
+        final Type[] args = new Type[size];
+        off = 1;
+        size = 0;
+        while ( buf[off] != ')' ) {
+            args[size] = getType( buf,
+                                  off );
+            off += args[size].len;
+            size += 1;
+        }
+        return args;
+    }
+
+    /**
+     * Returns the Java types corresponding to the argument types of the given
+     * method.
+     * 
+     * @param method a method.
+     * @return the Java types corresponding to the argument types of the given
+     *         method.
+     */
+    public static Type[] getArgumentTypes(final Method method) {
+        final Class[] classes = method.getParameterTypes();
+        final Type[] types = new Type[classes.length];
+        for ( int i = classes.length - 1; i >= 0; --i ) {
+            types[i] = getType( classes[i] );
+        }
+        return types;
+    }
+
+    /**
+     * Returns the Java type corresponding to the return type of the given
+     * method descriptor.
+     * 
+     * @param methodDescriptor a method descriptor.
+     * @return the Java type corresponding to the return type of the given
+     *         method descriptor.
+     */
+    public static Type getReturnType(final String methodDescriptor) {
+        final char[] buf = methodDescriptor.toCharArray();
+        return getType( buf,
+                        methodDescriptor.indexOf( ')' ) + 1 );
+    }
+
+    /**
+     * Returns the Java type corresponding to the return type of the given
+     * method.
+     * 
+     * @param method a method.
+     * @return the Java type corresponding to the return type of the given
+     *         method.
+     */
+    public static Type getReturnType(final Method method) {
+        return getType( method.getReturnType() );
+    }
+
+    /**
+     * Returns the Java type corresponding to the given type descriptor.
+     * 
+     * @param buf a buffer containing a type descriptor.
+     * @param off the offset of this descriptor in the previous buffer.
+     * @return the Java type corresponding to the given type descriptor.
+     */
+    private static Type getType(final char[] buf,
+                                final int off) {
+        int len;
+        switch ( buf[off] ) {
+            case 'V' :
+                return Type.VOID_TYPE;
+            case 'Z' :
+                return Type.BOOLEAN_TYPE;
+            case 'C' :
+                return Type.CHAR_TYPE;
+            case 'B' :
+                return Type.BYTE_TYPE;
+            case 'S' :
+                return Type.SHORT_TYPE;
+            case 'I' :
+                return Type.INT_TYPE;
+            case 'F' :
+                return Type.FLOAT_TYPE;
+            case 'J' :
+                return Type.LONG_TYPE;
+            case 'D' :
+                return Type.DOUBLE_TYPE;
+            case '[' :
+                len = 1;
+                while ( buf[off + len] == '[' ) {
+                    ++len;
+                }
+                if ( buf[off + len] == 'L' ) {
+                    ++len;
+                    while ( buf[off + len] != ';' ) {
+                        ++len;
+                    }
+                }
+                return new Type( Type.ARRAY,
+                                 buf,
+                                 off,
+                                 len + 1 );
+                // case 'L':
+            default :
+                len = 1;
+                while ( buf[off + len] != ';' ) {
+                    ++len;
+                }
+                return new Type( Type.OBJECT,
+                                 buf,
+                                 off,
+                                 len + 1 );
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Accessors
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns the sort of this Java type.
+     * 
+     * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN},
+     *         {@link #CHAR CHAR}, {@link #BYTE BYTE}, {@link #SHORT SHORT},
+     *         {@link #INT INT}, {@link #FLOAT FLOAT}, {@link #LONG LONG},
+     *         {@link #DOUBLE DOUBLE}, {@link #ARRAY ARRAY} or
+     *         {@link #OBJECT OBJECT}.
+     */
+    public int getSort() {
+        return this.sort;
+    }
+
+    /**
+     * Returns the number of dimensions of this array type. This method should
+     * only be used for an array type.
+     * 
+     * @return the number of dimensions of this array type.
+     */
+    public int getDimensions() {
+        int i = 1;
+        while ( this.buf[this.off + i] == '[' ) {
+            ++i;
+        }
+        return i;
+    }
+
+    /**
+     * Returns the type of the elements of this array type. This method should
+     * only be used for an array type.
+     * 
+     * @return Returns the type of the elements of this array type.
+     */
+    public Type getElementType() {
+        return getType( this.buf,
+                        this.off + getDimensions() );
+    }
+
+    /**
+     * Returns the name of the class corresponding to this type.
+     * 
+     * @return the fully qualified name of the class corresponding to this type.
+     */
+    public String getClassName() {
+        switch ( this.sort ) {
+            case VOID :
+                return "void";
+            case BOOLEAN :
+                return "boolean";
+            case CHAR :
+                return "char";
+            case BYTE :
+                return "byte";
+            case SHORT :
+                return "short";
+            case INT :
+                return "int";
+            case FLOAT :
+                return "float";
+            case LONG :
+                return "long";
+            case DOUBLE :
+                return "double";
+            case ARRAY :
+                final StringBuffer b = new StringBuffer( getElementType().getClassName() );
+                for ( int i = getDimensions(); i > 0; --i ) {
+                    b.append( "[]" );
+                }
+                return b.toString();
+                // case OBJECT:
+            default :
+                return new String( this.buf,
+                                   this.off + 1,
+                                   this.len - 2 ).replace( '/',
+                                                           '.' );
+        }
+    }
+
+    /**
+     * Returns the internal name of the class corresponding to this object type.
+     * The internal name of a class is its fully qualified name, where '.' are
+     * replaced by '/'. This method should only be used for an object type.
+     * 
+     * @return the internal name of the class corresponding to this object type.
+     */
+    public String getInternalName() {
+        return new String( this.buf,
+                           this.off + 1,
+                           this.len - 2 );
+    }
+
+    // ------------------------------------------------------------------------
+    // Conversion to type descriptors
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns the descriptor corresponding to this Java type.
+     * 
+     * @return the descriptor corresponding to this Java type.
+     */
+    public String getDescriptor() {
+        final StringBuffer buf = new StringBuffer();
+        getDescriptor( buf );
+        return buf.toString();
+    }
+
+    /**
+     * Returns the descriptor corresponding to the given argument and return
+     * types.
+     * 
+     * @param returnType the return type of the method.
+     * @param argumentTypes the argument types of the method.
+     * @return the descriptor corresponding to the given argument and return
+     *         types.
+     */
+    public static String getMethodDescriptor(final Type returnType,
+                                             final Type[] argumentTypes) {
+        final StringBuffer buf = new StringBuffer();
+        buf.append( '(' );
+        for ( int i = 0; i < argumentTypes.length; ++i ) {
+            argumentTypes[i].getDescriptor( buf );
+        }
+        buf.append( ')' );
+        returnType.getDescriptor( buf );
+        return buf.toString();
+    }
+
+    /**
+     * Appends the descriptor corresponding to this Java type to the given
+     * string buffer.
+     * 
+     * @param buf the string buffer to which the descriptor must be appended.
+     */
+    private void getDescriptor(final StringBuffer buf) {
+        switch ( this.sort ) {
+            case VOID :
+                buf.append( 'V' );
+                return;
+            case BOOLEAN :
+                buf.append( 'Z' );
+                return;
+            case CHAR :
+                buf.append( 'C' );
+                return;
+            case BYTE :
+                buf.append( 'B' );
+                return;
+            case SHORT :
+                buf.append( 'S' );
+                return;
+            case INT :
+                buf.append( 'I' );
+                return;
+            case FLOAT :
+                buf.append( 'F' );
+                return;
+            case LONG :
+                buf.append( 'J' );
+                return;
+            case DOUBLE :
+                buf.append( 'D' );
+                return;
+                // case ARRAY:
+                // case OBJECT:
+            default :
+                buf.append( this.buf,
+                            this.off,
+                            this.len );
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Direct conversion from classes to type descriptors,
+    // without intermediate Type objects
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns the internal name of the given class. The internal name of a
+     * class is its fully qualified name, where '.' are replaced by '/'.
+     * 
+     * @param c an object class.
+     * @return the internal name of the given class.
+     */
+    public static String getInternalName(final Class c) {
+        return c.getName().replace( '.',
+                                    '/' );
+    }
+
+    /**
+     * Returns the descriptor corresponding to the given Java type.
+     * 
+     * @param c an object class, a primitive class or an array class.
+     * @return the descriptor corresponding to the given class.
+     */
+    public static String getDescriptor(final Class c) {
+        final StringBuffer buf = new StringBuffer();
+        getDescriptor( buf,
+                       c );
+        return buf.toString();
+    }
+
+    /**
+     * Returns the descriptor corresponding to the given method.
+     * 
+     * @param m a {@link Method Method} object.
+     * @return the descriptor of the given method.
+     */
+    public static String getMethodDescriptor(final Method m) {
+        final Class[] parameters = m.getParameterTypes();
+        final StringBuffer buf = new StringBuffer();
+        buf.append( '(' );
+        for ( int i = 0; i < parameters.length; ++i ) {
+            getDescriptor( buf,
+                           parameters[i] );
+        }
+        buf.append( ')' );
+        getDescriptor( buf,
+                       m.getReturnType() );
+        return buf.toString();
+    }
+
+    /**
+     * Appends the descriptor of the given class to the given string buffer.
+     * 
+     * @param buf the string buffer to which the descriptor must be appended.
+     * @param c the class whose descriptor must be computed.
+     */
+    private static void getDescriptor(final StringBuffer buf,
+                                      final Class c) {
+        Class d = c;
+        while ( true ) {
+            if ( d.isPrimitive() ) {
+                char car;
+                if ( d == Integer.TYPE ) {
+                    car = 'I';
+                } else if ( d == Void.TYPE ) {
+                    car = 'V';
+                } else if ( d == Boolean.TYPE ) {
+                    car = 'Z';
+                } else if ( d == Byte.TYPE ) {
+                    car = 'B';
+                } else if ( d == Character.TYPE ) {
+                    car = 'C';
+                } else if ( d == Short.TYPE ) {
+                    car = 'S';
+                } else if ( d == Double.TYPE ) {
+                    car = 'D';
+                } else if ( d == Float.TYPE ) {
+                    car = 'F';
+                } else /* if (d == Long.TYPE) */{
+                    car = 'J';
+                }
+                buf.append( car );
+                return;
+            } else if ( d.isArray() ) {
+                buf.append( '[' );
+                d = d.getComponentType();
+            } else {
+                buf.append( 'L' );
+                final String name = d.getName();
+                final int len = name.length();
+                for ( int i = 0; i < len; ++i ) {
+                    final char car = name.charAt( i );
+                    buf.append( car == '.' ? '/' : car );
+                }
+                buf.append( ';' );
+                return;
+            }
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Corresponding size and opcodes
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns the size of values of this type.
+     * 
+     * @return the size of values of this type, i.e., 2 for <tt>long</tt> and
+     *         <tt>double</tt>, and 1 otherwise.
+     */
+    public int getSize() {
+        return (this.sort == Type.LONG || this.sort == Type.DOUBLE ? 2 : 1);
+    }
+
+    /**
+     * Returns a JVM instruction opcode adapted to this Java type.
+     * 
+     * @param opcode a JVM instruction opcode. This opcode must be one of ILOAD,
+     *        ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, ISHL,
+     *        ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.
+     * @return an opcode that is similar to the given opcode, but adapted to
+     *         this Java type. For example, if this type is <tt>float</tt> and
+     *         <tt>opcode</tt> is IRETURN, this method returns FRETURN.
+     */
+    public int getOpcode(final int opcode) {
+        if ( opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE ) {
+            switch ( this.sort ) {
+                case BOOLEAN :
+                case BYTE :
+                    return opcode + 5;
+                case CHAR :
+                    return opcode + 6;
+                case SHORT :
+                    return opcode + 7;
+                case INT :
+                    return opcode;
+                case FLOAT :
+                    return opcode + 2;
+                case LONG :
+                    return opcode + 1;
+                case DOUBLE :
+                    return opcode + 3;
+                    // case ARRAY:
+                    // case OBJECT:
+                default :
+                    return opcode + 4;
+            }
+        } else {
+            switch ( this.sort ) {
+                case VOID :
+                    return opcode + 5;
+                case BOOLEAN :
+                case CHAR :
+                case BYTE :
+                case SHORT :
+                case INT :
+                    return opcode;
+                case FLOAT :
+                    return opcode + 2;
+                case LONG :
+                    return opcode + 1;
+                case DOUBLE :
+                    return opcode + 3;
+                    // case ARRAY:
+                    // case OBJECT:
+                default :
+                    return opcode + 4;
+            }
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Equals, hashCode and toString
+    // ------------------------------------------------------------------------
+
+    /**
+     * Tests if the given object is equal to this type.
+     * 
+     * @param o the object to be compared to this type.
+     * @return <tt>true</tt> if the given object is equal to this type.
+     */
+    public boolean equals(final Object o) {
+        if ( this == o ) {
+            return true;
+        }
+        if ( o == null || !(o instanceof Type) ) {
+            return false;
+        }
+        final Type t = (Type) o;
+        if ( this.sort != t.sort ) {
+            return false;
+        }
+        if ( this.sort == Type.OBJECT || this.sort == Type.ARRAY ) {
+            if ( this.len != t.len ) {
+                return false;
+            }
+            for ( int i = this.off, j = t.off, end = i + this.len; i < end; i++, j++ ) {
+                if ( this.buf[i] != t.buf[j] ) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Returns a hash code value for this type.
+     * 
+     * @return a hash code value for this type.
+     */
+    public int hashCode() {
+        int hc = 13 * this.sort;
+        if ( this.sort == Type.OBJECT || this.sort == Type.ARRAY ) {
+            for ( int i = this.off, end = i + this.len; i < end; i++ ) {
+                hc = 17 * (hc + this.buf[i]);
+            }
+        }
+        return hc;
+    }
+
+    /**
+     * Returns a string representation of this type.
+     * 
+     * @return the descriptor of this type.
+     */
+    public String toString() {
+        return getDescriptor();
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/attrs/StackMapAttribute.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/attrs/StackMapAttribute.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/attrs/StackMapAttribute.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,389 @@
+/**
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.attrs;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.drools.asm.Attribute;
+import org.drools.asm.ByteVector;
+import org.drools.asm.ClassReader;
+import org.drools.asm.ClassWriter;
+import org.drools.asm.Label;
+
+/**
+ * StackMapAttribute is used by CDLC preverifier. Definition is given in
+ * appendix "CLDC Byte Code Typechecker Specification" from CDLC 1.1
+ * specification. <p> <i>Note that this implementation does not calculate
+ * StackMapFrame structures from the method bytecode. If method code is changed
+ * or generated from scratch, then developer is responsible to prepare a correct
+ * StackMapFrame structures.</i> <p> The format of the stack map in the class
+ * file is given below. In the following, <ul> <li>if the length of the
+ * method's byte code1 is 65535 or less, then <tt>uoffset</tt> represents the
+ * type u2; otherwise <tt>uoffset</tt> represents the type u4.</li> <li>If
+ * the maximum number of local variables for the method is 65535 or less, then
+ * <tt>ulocalvar</tt> represents the type u2; otherwise <tt>ulocalvar</tt>
+ * represents the type u4.</li> <li>If the maximum size of the operand stack
+ * is 65535 or less, then <tt>ustack</tt> represents the type u2; otherwise
+ * ustack represents the type u4.</li> </ul>
+ * 
+ * <pre>
+ * stack_map { // attribute StackMap
+ *   u2 attribute_name_index;
+ *   u4 attribute_length
+ *   uoffset number_of_entries;
+ *   stack_map_frame entries[number_of_entries];
+ * }
+ * </pre>
+ * 
+ * Each stack map frame has the following format:
+ * 
+ * <pre>
+ * stack_map_frame {
+ *   uoffset offset;
+ *   ulocalvar number_of_locals;
+ *   verification_type_info locals[number_of_locals];
+ *   ustack number_of_stack_items;
+ *   verification_type_info stack[number_of_stack_items];
+ * }
+ * </pre>
+ * 
+ * The <tt>verification_type_info</tt> structure consists of a one-byte tag
+ * followed by zero or more bytes, giving more information about the tag. Each
+ * <tt>verification_type_info</tt> structure specifies the verification type
+ * of one or two locations.
+ * 
+ * <pre>
+ * union verification_type_info {
+ *   Top_variable_info;
+ *   Integer_variable_info;
+ *   Float_variable_info;
+ *   Long_variable_info;
+ *   Double_variable_info;
+ *   Null_variable_info;
+ *   UninitializedThis_variable_info;
+ *   Object_variable_info;
+ *   Uninitialized_variable_info;
+ * }
+ *      
+ * Top_variable_info {
+ *   u1 tag = ITEM_Top; // 0
+ * }
+ *      
+ * Integer_variable_info {
+ *   u1 tag = ITEM_Integer; // 1
+ * }
+ *      
+ * Float_variable_info {
+ *   u1 tag = ITEM_Float; // 2
+ * }
+ *      
+ * Long_variable_info {
+ *   u1 tag = ITEM_Long; // 4
+ * }
+ *      
+ * Double_variable_info {
+ *   u1 tag = ITEM_Double; // 3
+ * }
+ *      
+ * Null_variable_info {
+ *  u1 tag = ITEM_Null; // 5
+ * }
+ *      
+ * UninitializedThis_variable_info {
+ *   u1 tag = ITEM_UninitializedThis; // 6
+ * }
+ *      
+ * Object_variable_info {
+ *   u1 tag = ITEM_Object; // 7
+ *   u2 cpool_index;
+ * }
+ *      
+ * Uninitialized_variable_info {
+ *   u1 tag = ITEM_Uninitialized // 8
+ *   uoffset offset;
+ * }
+ * </pre>
+ * 
+ * @see <a href="http://www.jcp.org/en/jsr/detail?id=139">JSR 139 : Connected
+ *      Limited Device Configuration 1.1</a>
+ * 
+ * @author Eugene Kuleshov
+ */
+public class StackMapAttribute extends Attribute {
+
+    static final int MAX_SIZE = 65535;
+
+    /**
+     * A List of <code>StackMapFrame</code> instances.
+     */
+    public List      frames   = new ArrayList();
+
+    public StackMapAttribute() {
+        super( "StackMap" );
+    }
+
+    public StackMapAttribute(final List frames) {
+        this();
+        this.frames = frames;
+    }
+
+    public List getFrames() {
+        return this.frames;
+    }
+
+    public StackMapFrame getFrame(final Label label) {
+        for ( int i = 0; i < this.frames.size(); i++ ) {
+            final StackMapFrame frame = (StackMapFrame) this.frames.get( i );
+            if ( frame.label == label ) {
+                return frame;
+            }
+        }
+        return null;
+    }
+
+    public boolean isUnknown() {
+        return false;
+    }
+
+    public boolean isCodeAttribute() {
+        return true;
+    }
+
+    protected Attribute read(final ClassReader cr,
+                             int off,
+                             final int len,
+                             final char[] buf,
+                             final int codeOff,
+                             final Label[] labels) {
+        final StackMapAttribute attr = new StackMapAttribute();
+        // note that this is not the size of Code attribute
+        final boolean isExtCodeSize = cr.readInt( codeOff + 4 ) > StackMapAttribute.MAX_SIZE;
+        final boolean isExtLocals = cr.readUnsignedShort( codeOff + 2 ) > StackMapAttribute.MAX_SIZE;
+        final boolean isExtStack = cr.readUnsignedShort( codeOff ) > StackMapAttribute.MAX_SIZE;
+
+        int size = 0;
+        if ( isExtCodeSize ) {
+            size = cr.readInt( off );
+            off += 4;
+        } else {
+            size = cr.readUnsignedShort( off );
+            off += 2;
+        }
+        for ( int i = 0; i < size; i++ ) {
+            int offset;
+            if ( isExtCodeSize ) {
+                offset = cr.readInt( off );
+                off += 4;
+            } else {
+                offset = cr.readUnsignedShort( off );
+                off += 2;
+            }
+
+            final Label label = getLabel( offset,
+                                          labels );
+            final List locals = new ArrayList();
+            final List stack = new ArrayList();
+
+            off = readTypeInfo( cr,
+                                off,
+                                locals,
+                                labels,
+                                buf,
+                                isExtLocals,
+                                isExtCodeSize );
+            off = readTypeInfo( cr,
+                                off,
+                                stack,
+                                labels,
+                                buf,
+                                isExtStack,
+                                isExtCodeSize );
+
+            attr.frames.add( new StackMapFrame( label,
+                                                locals,
+                                                stack ) );
+        }
+        return attr;
+    }
+
+    private int readTypeInfo(final ClassReader cr,
+                             int off,
+                             final List info,
+                             final Label[] labels,
+                             final char[] buf,
+                             final boolean isExt,
+                             final boolean isExtCode) {
+        int n = 0;
+        if ( isExt ) {
+            n = cr.readInt( off );
+            off += 4;
+        } else {
+            n = cr.readUnsignedShort( off );
+            off += 2;
+        }
+        for ( int j = 0; j < n; j++ ) {
+            final int itemType = cr.readByte( off++ );
+            final StackMapType typeInfo = StackMapType.getTypeInfo( itemType );
+            info.add( typeInfo );
+            switch ( itemType ) {
+                case StackMapType.ITEM_Object : //
+                    typeInfo.setObject( cr.readClass( off,
+                                                      buf ) );
+                    off += 2;
+                    break;
+                case StackMapType.ITEM_Uninitialized : //
+                    int offset;
+                    if ( isExtCode ) {
+                        offset = cr.readInt( off );
+                        off += 4;
+                    } else {
+                        offset = cr.readUnsignedShort( off );
+                        off += 2;
+                    }
+                    typeInfo.setLabel( getLabel( offset,
+                                                 labels ) );
+                    break;
+            }
+        }
+        return off;
+    }
+
+    private void writeTypeInfo(final ByteVector bv,
+                               final ClassWriter cw,
+                               final List info,
+                               final int max) {
+        if ( max > StackMapAttribute.MAX_SIZE ) {
+            bv.putInt( info.size() );
+        } else {
+            bv.putShort( info.size() );
+        }
+        for ( int j = 0; j < info.size(); j++ ) {
+            final StackMapType typeInfo = (StackMapType) info.get( j );
+            bv.putByte( typeInfo.getType() );
+            switch ( typeInfo.getType() ) {
+                case StackMapType.ITEM_Object : //
+                    bv.putShort( cw.newClass( typeInfo.getObject() ) );
+                    break;
+
+                case StackMapType.ITEM_Uninitialized : //
+                    bv.putShort( typeInfo.getLabel().getOffset() );
+                    break;
+
+            }
+        }
+    }
+
+    private Label getLabel(final int offset,
+                           final Label[] labels) {
+        final Label l = labels[offset];
+        if ( l != null ) {
+            return l;
+        }
+        return labels[offset] = new Label();
+    }
+
+    protected ByteVector write(final ClassWriter cw,
+                               final byte[] code,
+                               final int len,
+                               final int maxStack,
+                               final int maxLocals) {
+        final ByteVector bv = new ByteVector();
+        if ( code != null && code.length > StackMapAttribute.MAX_SIZE ) { // TODO verify value
+            bv.putInt( this.frames.size() );
+        } else {
+            bv.putShort( this.frames.size() );
+        }
+        for ( int i = 0; i < this.frames.size(); i++ ) {
+            writeFrame( (StackMapFrame) this.frames.get( i ),
+                        cw,
+                        maxStack,
+                        maxLocals,
+                        bv );
+        }
+        return bv;
+    }
+
+    protected Label[] getLabels() {
+        final HashSet labels = new HashSet();
+        for ( int i = 0; i < this.frames.size(); i++ ) {
+            getFrameLabels( (StackMapFrame) this.frames.get( i ),
+                            labels );
+        }
+        return (Label[]) labels.toArray( new Label[labels.size()] );
+    }
+
+    private void writeFrame(final StackMapFrame frame,
+                            final ClassWriter cw,
+                            final int maxStack,
+                            final int maxLocals,
+                            final ByteVector bv) {
+        bv.putShort( frame.label.getOffset() );
+        writeTypeInfo( bv,
+                       cw,
+                       frame.locals,
+                       maxLocals );
+        writeTypeInfo( bv,
+                       cw,
+                       frame.stack,
+                       maxStack );
+    }
+
+    private void getFrameLabels(final StackMapFrame frame,
+                                final Set labels) {
+        labels.add( frame.label );
+        getTypeInfoLabels( labels,
+                           frame.locals );
+        getTypeInfoLabels( labels,
+                           frame.stack );
+    }
+
+    private void getTypeInfoLabels(final Set labels,
+                                   final List info) {
+        for ( final Iterator it = info.iterator(); it.hasNext(); ) {
+            final StackMapType typeInfo = (StackMapType) it.next();
+            if ( typeInfo.getType() == StackMapType.ITEM_Uninitialized ) {
+                labels.add( typeInfo.getLabel() );
+            }
+        }
+    }
+
+    public String toString() {
+        final StringBuffer sb = new StringBuffer( "StackMap[" );
+        for ( int i = 0; i < this.frames.size(); i++ ) {
+            sb.append( '\n' ).append( '[' ).append( this.frames.get( i ) ).append( ']' );
+        }
+        sb.append( "\n]" );
+        return sb.toString();
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/attrs/StackMapFrame.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/attrs/StackMapFrame.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/attrs/StackMapFrame.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,84 @@
+/**
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.attrs;
+
+import java.util.List;
+
+import org.drools.asm.Label;
+
+/**
+ * Holds the state of the stack and local variables for a single execution
+ * branch.
+ * 
+ * <i>Note that Long and Double types are represented by two entries in locals
+ * and stack. Second entry should be always of type Top.</i>
+ * 
+ * @see <a href="http://www.jcp.org/en/jsr/detail?id=139">JSR 139 : Connected
+ *      Limited Device Configuration 1.1</a>
+ * 
+ * @see "ClassFileFormat-Java6.fm Page 138 Friday, April 15, 2005 3:22 PM"
+ * 
+ * @author Eugene Kuleshov
+ */
+public class StackMapFrame {
+
+    /**
+     * A <code>Label</code> for frame offset within method bytecode.
+     */
+    public Label label;
+
+    /**
+     * A List of <code>StackMapType</code> instances that represent locals for
+     * this frame.
+     */
+    public List  locals;
+
+    /**
+     * A List of <code>StackMapType</code> instances that represent stack for
+     * this frame.
+     */
+    public List  stack;
+
+    public StackMapFrame(final Label label,
+                         final List locals,
+                         final List stack) {
+        this.label = label;
+        this.locals = locals;
+        this.stack = stack;
+    }
+
+    public String toString() {
+        final StringBuffer sb = new StringBuffer( "Frame:L" );
+        sb.append( System.identityHashCode( this.label ) );
+        sb.append( " locals" ).append( this.locals );
+        sb.append( " stack" ).append( this.stack );
+        return sb.toString();
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/attrs/StackMapTableAttribute.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/attrs/StackMapTableAttribute.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/attrs/StackMapTableAttribute.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,975 @@
+/**
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.attrs;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.drools.asm.Attribute;
+import org.drools.asm.ByteVector;
+import org.drools.asm.ClassReader;
+import org.drools.asm.ClassWriter;
+import org.drools.asm.Label;
+import org.drools.asm.Opcodes;
+import org.drools.asm.Type;
+
+/**
+ * The stack map attribute is used during the process of verification by
+ * typechecking (4.11.1). <br> <br> A stack map attribute consists of zero or
+ * more stack map frames. Each stack map frame specifies (either explicitly or
+ * implicitly) a bytecode offset, the verification types (4.11.1) for the local
+ * variables, and the verification types for the operand stack. <br> <br> The
+ * type checker deals with and manipulates the expected types of a method's
+ * local variables and operand stack. Throughout this section, a location refers
+ * to either a single local variable or to a single operand stack entry. <br>
+ * <br> We will use the terms stack frame map and type state interchangeably to
+ * describe a mapping from locations in the operand stack and local variables of
+ * a method to verification types. We will usually use the term stack frame map
+ * when such a mapping is provided in the class file, and the term type state
+ * when the mapping is inferred by the type checker. <br> <br> If a method's
+ * Code attribute does not have a StackMapTable attribute, it has an implicit
+ * stack map attribute. This implicit stack map attribute is equivalent to a
+ * StackMapTable attribute with number_of_entries equal to zero. A method's Code
+ * attribute may have at most one StackMapTable attribute, otherwise a
+ * java.lang.ClassFormatError is thrown. <br> <br> The format of the stack map
+ * in the class file is given below. In the following, if the length of the
+ * method's byte code is 65535 or less, then uoffset represents the type u2;
+ * otherwise uoffset represents the type u4. If the maximum number of local
+ * variables for the method is 65535 or less, then <code>ulocalvar</code>
+ * represents the type u2; otherwise ulocalvar represents the type u4. If the
+ * maximum size of the operand stack is 65535 or less, then <code>ustack</code>
+ * represents the type u2; otherwise ustack represents the type u4.
+ * 
+ * <pre>
+ * stack_map { // attribute StackMapTable
+ *   u2 attribute_name_index;
+ *   u4 attribute_length
+ *   uoffset number_of_entries;
+ *   stack_map_frame entries[number_of_entries];
+ * }
+ * </pre>
+ * 
+ * Each stack_map_frame structure specifies the type state at a particular byte
+ * code offset. Each frame type specifies (explicitly or implicitly) a value,
+ * offset_delta, that is used to calulate the actual byte code offset at which
+ * it applies. The byte code offset at which the frame applies is given by
+ * adding <code>1 + offset_delta</code> to the <code>offset</code> of the
+ * previous frame, unless the previous frame is the initial frame of the method,
+ * in which case the byte code offset is <code>offset_delta</code>. <br> <br>
+ * <i>Note that the length of the byte codes is not the same as the length of
+ * the Code attribute. The byte codes are embedded in the Code attribute, along
+ * with other information.</i> <br> <br> By using an offset delta rather than
+ * the actual byte code offset we ensure, by definition, that stack map frames
+ * are in the correctly sorted order. Furthermore, by consistently using the
+ * formula <code>offset_delta + 1</code> for all explicit frames, we guarantee
+ * the absence of duplicates. <br> <br> All frame types, even full_frame, rely
+ * on the previous frame for some of their semantics. This raises the question
+ * of what is the very first frame? The initial frame is implicit, and computed
+ * from the method descriptor. See the Prolog code for methodInitialStacFrame.
+ * <br> <br> The stack_map_frame structure consists of a one-byte tag followed
+ * by zero or more bytes, giving more information, depending upon the tag. <br>
+ * <br> A stack map frame may belong to one of several frame types
+ * 
+ * <pre>
+ * union stack_map_frame {
+ *   same_frame;
+ *   same_locals_1_stack_item_frame;
+ *   chop_frame;
+ *   same_frame_extended;
+ *   append_frame;
+ *   full_frame;
+ * }
+ * </pre>
+ * 
+ * The frame type same_frame is represented by tags in the range [0-63]. If the
+ * frame type is same_frame, it means the frame has exactly the same locals as
+ * the previous stack map frame and that the number of stack items is zero. The
+ * offset_delta value for the frame is the value of the tag field, frame_type.
+ * The form of such a frame is then:
+ * 
+ * <pre>
+ * same_frame {
+ *   u1 frame_type = SAME;  // 0-63
+ * }
+ * </pre>
+ * 
+ * The frame type same_locals_1_stack_item_frame is represented by tags in the
+ * range [64, 127]. If the frame_type is same_locals_1_stack_item_frame, it
+ * means the frame has exactly the same locals as the previous stack map frame
+ * and that the number of stack items is 1. The offset_delta value for the frame
+ * is the value (frame_type - 64). There is a verification_type_info following
+ * the frame_type for the one stack item. The form of such a frame is then:
+ * 
+ * <pre>
+ * same_locals_1_stack_item_frame {
+ *   u1 frame_type = SAME_LOCALS_1_STACK_ITEM;  // 64-127
+ *    verification_type_info stack[1];
+ * }
+ * </pre>
+ * 
+ * Tags in the range [128-247] are reserved for future use. <br> <br> The frame
+ * type chop_frame is represented by tags in the range [248-250]. If the
+ * frame_type is chop_frame, it means that the current locals are the same as
+ * the locals in the previous frame, except that the k last locals are absent.
+ * The value of k is given by the formula 251-frame_type. <br> <br> The form of
+ * such a frame is then:
+ * 
+ * <pre>
+ * chop_frame {
+ *   u1 frame_type=CHOP;  // 248-250
+ *   uoffset offset_delta;
+ * }
+ * </pre>
+ * 
+ * The frame type same_frame_extended is represented by the tag value 251. If
+ * the frame type is same_frame_extended, it means the frame has exactly the
+ * same locals as the previous stack map frame and that the number of stack
+ * items is zero. The form of such a frame is then:
+ * 
+ * <pre>
+ * same_frame_extended {
+ *   u1 frame_type = SAME_FRAME_EXTENDED;  // 251
+ *   uoffset offset_delta;
+ * }
+ * </pre>
+ * 
+ * The frame type append_frame is represented by tags in the range [252-254]. If
+ * the frame_type is append_frame, it means that the current locals are the same
+ * as the locals in the previous frame, except that k additional locals are
+ * defined. The value of k is given by the formula frame_type-251. <br> <br> The
+ * form of such a frame is then:
+ * 
+ * <pre>
+ * append_frame {
+ *   u1 frame_type =APPEND;  // 252-254
+ *   uoffset offset_delta;
+ *   verification_type_info locals[frame_type -251];
+ * }
+ * </pre>
+ * 
+ * The 0th entry in locals represents the type of the first additional local
+ * variable. If locals[M] represents local variable N, then locals[M+1]
+ * represents local variable N+1 if locals[M] is one of Top_variable_info,
+ * Integer_variable_info, Float_variable_info, Null_variable_info,
+ * UninitializedThis_variable_info, Object_variable_info, or
+ * Uninitialized_variable_info, otherwise locals[M+1] represents local variable
+ * N+2. It is an error if, for any index i, locals[i] represents a local
+ * variable whose index is greater than the maximum number of local variables
+ * for the method. <br> <br> The frame type full_frame is represented by the tag
+ * value 255. The form of such a frame is then:
+ * 
+ * <pre>
+ * full_frame {
+ *   u1 frame_type = FULL_FRAME;  // 255
+ *   uoffset offset_delta;
+ *   ulocalvar number_of_locals;
+ *   verification_type_info locals[number_of_locals];
+ *   ustack number_of_stack_items;
+ *   verification_type_info stack[number_of_stack_items];
+ * }
+ * </pre>
+ * 
+ * The 0th entry in locals represents the type of local variable 0. If locals[M]
+ * represents local variable N, then locals[M+1] represents local variable N+1
+ * if locals[M] is one of Top_variable_info, Integer_variable_info,
+ * Float_variable_info, Null_variable_info, UninitializedThis_variable_info,
+ * Object_variable_info, or Uninitialized_variable_info, otherwise locals[M+1]
+ * represents local variable N+2. It is an error if, for any index i, locals[i]
+ * represents a local variable whose index is greater than the maximum number of
+ * local variables for the method. <br> <br> The 0th entry in stack represents
+ * the type of the bottom of the stack, and subsequent entries represent types
+ * of stack elements closer to the top of the operand stack. We shall refer to
+ * the bottom element of the stack as stack element 0, and to subsequent
+ * elements as stack element 1, 2 etc. If stack[M] represents stack element N,
+ * then stack[M+1] represents stack element N+1 if stack[M] is one of
+ * Top_variable_info, Integer_variable_info, Float_variable_info,
+ * Null_variable_info, UninitializedThis_variable_info, Object_variable_info, or
+ * Uninitialized_variable_info, otherwise stack[M+1] represents stack element
+ * N+2. It is an error if, for any index i, stack[i] represents a stack entry
+ * whose index is greater than the maximum operand stack size for the method.
+ * <br> <br> We say that an instruction in the byte code has a corresponding
+ * stack map frame if the offset in the offset field of the stack map frame is
+ * the same as the offset of the instruction in the byte codes. <br> <br> The
+ * verification_type_info structure consists of a one-byte tag followed by zero
+ * or more bytes, giving more information about the tag. Each
+ * verification_type_info structure specifies the verification type of one or
+ * two locations.
+ * 
+ * <pre>
+ * union verification_type_info {
+ *   Top_variable_info;
+ *   Integer_variable_info;
+ *   Float_variable_info;
+ *   Long_variable_info;
+ *   Double_variable_info;
+ *   Null_variable_info;
+ *   UninitializedThis_variable_info;
+ *   Object_variable_info;
+ *   Uninitialized_variable_info;
+ * }
+ * </pre>
+ * 
+ * The Top_variable_info type indicates that the local variable has the
+ * verification type top (T.)
+ * 
+ * <pre>
+ * Top_variable_info {
+ *   u1 tag = ITEM_Top; // 0
+ * }
+ * </pre>
+ * 
+ * The Integer_variable_info type indicates that the location contains the
+ * verification type int.
+ * 
+ * <pre>
+ * Integer_variable_info {
+ *   u1 tag = ITEM_Integer; // 1
+ * }
+ * </pre>
+ * 
+ * The Float_variable_info type indicates that the location contains the
+ * verification type float.
+ * 
+ * <pre>
+ * Float_variable_info {
+ *   u1 tag = ITEM_Float; // 2
+ * }
+ * </pre>
+ * 
+ * The Long_variable_info type indicates that the location contains the
+ * verification type long. If the location is a local variable, then:
+ * 
+ * <ul> <li>It must not be the local variable with the highest index.</li>
+ * <li>The next higher numbered local variable contains the verification type
+ * T.</li> </ul>
+ * 
+ * If the location is an operand stack entry, then:
+ * 
+ * <ul> <li>The current location must not be the topmost location of the
+ * operand stack.</li> <li>the next location closer to the top of the operand
+ * stack contains the verification type T.</li> </ul>
+ * 
+ * This structure gives the contents of two locations in the operand stack or in
+ * the local variables.
+ * 
+ * <pre>
+ * Long_variable_info {
+ *   u1 tag = ITEM_Long; // 4
+ * }
+ * </pre>
+ * 
+ * The Double_variable_info type indicates that the location contains the
+ * verification type double. If the location is a local variable, then:
+ * 
+ * <ul> <li>It must not be the local variable with the highest index.</li>
+ * <li>The next higher numbered local variable contains the verification type
+ * T. <li> </ul>
+ * 
+ * If the location is an operand stack entry, then:
+ * 
+ * <ul> <li>The current location must not be the topmost location of the
+ * operand stack.</li> <li>the next location closer to the top of the operand
+ * stack contains the verification type T.</li> </ul>
+ * 
+ * This structure gives the contents of two locations in in the operand stack or
+ * in the local variables.
+ * 
+ * <pre>
+ * Double_variable_info {
+ *   u1 tag = ITEM_Double; // 3
+ * }
+ * </pre>
+ * 
+ * The Null_variable_info type indicates that location contains the verification
+ * type null.
+ * 
+ * <pre>
+ * Null_variable_info {
+ *   u1 tag = ITEM_Null; // 5
+ * }
+ * </pre>
+ * 
+ * The UninitializedThis_variable_info type indicates that the location contains
+ * the verification type uninitializedThis.
+ * 
+ * <pre>
+ * UninitializedThis_variable_info {
+ *   u1 tag = ITEM_UninitializedThis; // 6
+ * }
+ * </pre>
+ * 
+ * The Object_variable_info type indicates that the location contains an
+ * instance of the class referenced by the constant pool entry.
+ * 
+ * <pre>
+ * Object_variable_info {
+ *   u1 tag = ITEM_Object; // 7
+ *   u2 cpool_index;
+ * }
+ * </pre>
+ * 
+ * The Uninitialized_variable_info indicates that the location contains the
+ * verification type uninitialized(offset). The offset item indicates the offset
+ * of the new instruction that created the object being stored in the location.
+ * 
+ * <pre>
+ * Uninitialized_variable_info {
+ *   u1 tag = ITEM_Uninitialized // 8
+ *   uoffset offset;
+ * }
+ * </pre>
+ * 
+ * @see "ClassFileFormat-Java6.fm Page 138 Friday, April 15, 2005 3:22 PM"
+ * 
+ * @author Eugene Kuleshov
+ */
+public class StackMapTableAttribute extends Attribute {
+    /**
+     * Frame has exactly the same locals as the previous stack map frame and
+     * number of stack items is zero.
+     */
+    public static final int  SAME_FRAME                              = 0;    // to 63 (0-3f)
+
+    /**
+     * Frame has exactly the same locals as the previous stack map frame and
+     * number of stack items is 1
+     */
+    public static final int  SAME_LOCALS_1_STACK_ITEM_FRAME          = 64;   // to 127
+
+    // (40-7f)
+
+    /**
+     * Reserved for future use
+     */
+    public static final int  RESERVED                                = 128;
+
+    /**
+     * Frame has exactly the same locals as the previous stack map frame and
+     * number of stack items is 1. Offset is bigger then 63;
+     */
+    public static final int  SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247;  // f7
+
+    /**
+     * Frame where current locals are the same as the locals in the previous
+     * frame, except that the k last locals are absent. The value of k is given
+     * by the formula 251-frame_type.
+     */
+    public static final int  CHOP_FRAME                              = 248;  // to 250 (f8-fA)
+
+    /**
+     * Frame has exactly the same locals as the previous stack map frame and
+     * number of stack items is zero. Offset is bigger then 63;
+     */
+    public static final int  SAME_FRAME_EXTENDED                     = 251;  // fb
+
+    /**
+     * Frame where current locals are the same as the locals in the previous
+     * frame, except that k additional locals are defined. The value of k is
+     * given by the formula frame_type-251.
+     */
+    public static final int  APPEND_FRAME                            = 252;  // to 254 // fc-fe
+
+    /**
+     * Full frame
+     */
+    public static final int  FULL_FRAME                              = 255;  // ff
+
+    private static final int MAX_SHORT                               = 65535;
+
+    /**
+     * A <code>List</code> of <code>StackMapFrame</code> instances.
+     */
+    private List             frames;
+
+    public StackMapTableAttribute() {
+        super( "StackMapTable" );
+    }
+
+    public StackMapTableAttribute(final List frames) {
+        this();
+        this.frames = frames;
+    }
+
+    public List getFrames() {
+        return this.frames;
+    }
+
+    public StackMapFrame getFrame(final Label label) {
+        for ( int i = 0; i < this.frames.size(); i++ ) {
+            final StackMapFrame frame = (StackMapFrame) this.frames.get( i );
+            if ( frame.label == label ) {
+                return frame;
+            }
+        }
+        return null;
+    }
+
+    public boolean isUnknown() {
+        return false;
+    }
+
+    public boolean isCodeAttribute() {
+        return true;
+    }
+
+    protected Attribute read(final ClassReader cr,
+                             int off,
+                             final int len,
+                             final char[] buf,
+                             final int codeOff,
+                             final Label[] labels) {
+
+        final ArrayList frames = new ArrayList();
+
+        // note that this is not the size of Code attribute
+        final boolean isExtCodeSize = cr.readInt( codeOff + 4 ) > StackMapTableAttribute.MAX_SHORT;
+        final boolean isExtLocals = cr.readUnsignedShort( codeOff + 2 ) > StackMapTableAttribute.MAX_SHORT;
+        final boolean isExtStack = cr.readUnsignedShort( codeOff ) > StackMapTableAttribute.MAX_SHORT;
+
+        int offset = 0;
+
+        final int methodOff = getMethodOff( cr,
+                                            codeOff,
+                                            buf );
+        StackMapFrame frame = new StackMapFrame( getLabel( offset,
+                                                           labels ),
+                                                 calculateLocals( cr.readClass( cr.header + 2,
+                                                                                buf ), // owner
+                                                                  cr.readUnsignedShort( methodOff ), // method access
+                                                                  cr.readUTF8( methodOff + 2,
+                                                                               buf ), // method name
+                                                                  cr.readUTF8( methodOff + 4,
+                                                                               buf ) ), // method desc
+                                                 Collections.EMPTY_LIST );
+        frames.add( frame );
+
+        // System.err.println( cr.readUTF8( methodOff + 2, buf));
+        // System.err.println( offset +" delta:" + 0 +" : "+ frame);
+
+        int size;
+        if ( isExtCodeSize ) {
+            size = cr.readInt( off );
+            off += 4;
+        } else {
+            size = cr.readUnsignedShort( off );
+            off += 2;
+        }
+
+        for ( ; size > 0; size-- ) {
+            final int tag = cr.readByte( off ); // & 0xff;
+            off++;
+
+            List stack;
+            List locals;
+
+            int offsetDelta;
+            if ( tag < StackMapTableAttribute.SAME_LOCALS_1_STACK_ITEM_FRAME ) { // SAME_FRAME
+                offsetDelta = tag;
+
+                locals = new ArrayList( frame.locals );
+                stack = Collections.EMPTY_LIST;
+
+            } else if ( tag < StackMapTableAttribute.RESERVED ) { // SAME_LOCALS_1_STACK_ITEM_FRAME
+                offsetDelta = tag - StackMapTableAttribute.SAME_LOCALS_1_STACK_ITEM_FRAME;
+
+                locals = new ArrayList( frame.locals );
+                stack = new ArrayList();
+                // read verification_type_info stack[1];
+                off = readType( stack,
+                                isExtCodeSize,
+                                cr,
+                                off,
+                                labels,
+                                buf );
+
+            } else {
+                if ( isExtCodeSize ) {
+                    offsetDelta = cr.readInt( off );
+                    off += 4;
+                } else {
+                    offsetDelta = cr.readUnsignedShort( off );
+                    off += 2;
+                }
+
+                if ( tag == StackMapTableAttribute.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED ) { // SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED
+                    locals = new ArrayList( frame.locals );
+                    stack = new ArrayList();
+                    // read verification_type_info stack[1];
+                    off = readType( stack,
+                                    isExtCodeSize,
+                                    cr,
+                                    off,
+                                    labels,
+                                    buf );
+
+                } else if ( tag >= StackMapTableAttribute.CHOP_FRAME && tag < StackMapTableAttribute.SAME_FRAME_EXTENDED ) { // CHOP_FRAME
+                    stack = Collections.EMPTY_LIST;
+
+                    final int k = StackMapTableAttribute.SAME_FRAME_EXTENDED - tag;
+                    // copy locals from prev frame and chop last k
+                    locals = new ArrayList( frame.locals.subList( 0,
+                                                                  frame.locals.size() - k ) );
+
+                } else if ( tag == StackMapTableAttribute.SAME_FRAME_EXTENDED ) { // SAME_FRAME_EXTENDED
+                    stack = Collections.EMPTY_LIST;
+                    locals = new ArrayList( frame.locals );
+
+                } else if ( /* tag>=APPEND && */tag < StackMapTableAttribute.FULL_FRAME ) { // APPEND_FRAME
+                    stack = Collections.EMPTY_LIST;
+
+                    // copy locals from prev frame and append new k
+                    locals = new ArrayList( frame.locals );
+                    for ( int k = tag - StackMapTableAttribute.SAME_FRAME_EXTENDED; k > 0; k-- ) {
+                        off = readType( locals,
+                                        isExtCodeSize,
+                                        cr,
+                                        off,
+                                        labels,
+                                        buf );
+                    }
+
+                } else if ( tag == StackMapTableAttribute.FULL_FRAME ) { // FULL_FRAME
+                    // read verification_type_info locals[number_of_locals];
+                    locals = new ArrayList();
+                    off = readTypes( locals,
+                                     isExtLocals,
+                                     isExtCodeSize,
+                                     cr,
+                                     off,
+                                     labels,
+                                     buf );
+
+                    // read verification_type_info stack[number_of_stack_items];
+                    stack = new ArrayList();
+                    off = readTypes( stack,
+                                     isExtStack,
+                                     isExtCodeSize,
+                                     cr,
+                                     off,
+                                     labels,
+                                     buf );
+
+                } else {
+                    throw new RuntimeException( "Unknown frame type " + tag + " after offset " + offset );
+
+                }
+            }
+
+            offset += offsetDelta;
+
+            final Label offsetLabel = getLabel( offset,
+                                                labels );
+
+            frame = new StackMapFrame( offsetLabel,
+                                       locals,
+                                       stack );
+            frames.add( frame );
+            // System.err.println( tag +" " + offset +" delta:" + offsetDelta +
+            // " frameType:"+ frameType+" : "+ frame);
+
+            offset++;
+        }
+
+        return new StackMapTableAttribute( frames );
+    }
+
+    protected ByteVector write(final ClassWriter cw,
+                               final byte[] code,
+                               final int len,
+                               final int maxStack,
+                               final int maxLocals) {
+        final ByteVector bv = new ByteVector();
+        // TODO verify this value (MAX_SHORT)
+        final boolean isExtCodeSize = code != null && code.length > StackMapTableAttribute.MAX_SHORT;
+        writeSize( this.frames.size() - 1,
+                   bv,
+                   isExtCodeSize );
+
+        if ( this.frames.size() < 2 ) {
+            return bv;
+        }
+
+        final boolean isExtLocals = maxLocals > StackMapTableAttribute.MAX_SHORT;
+        final boolean isExtStack = maxStack > StackMapTableAttribute.MAX_SHORT;
+
+        // skip the first frame
+        StackMapFrame frame = (StackMapFrame) this.frames.get( 0 );
+        List locals = frame.locals;
+        int offset = frame.label.getOffset();
+
+        for ( int i = 1; i < this.frames.size(); i++ ) {
+            frame = (StackMapFrame) this.frames.get( i );
+
+            final List clocals = frame.locals;
+            final List cstack = frame.stack;
+            final int coffset = frame.label.getOffset();
+
+            final int clocalsSize = clocals.size();
+            final int cstackSize = cstack.size();
+
+            int localsSize = locals.size();
+
+            final int delta = coffset - offset;
+
+            int type = StackMapTableAttribute.FULL_FRAME;
+            int k = 0;
+            if ( cstackSize == 0 ) {
+                k = clocalsSize - localsSize;
+                switch ( k ) {
+                    case -3 :
+                    case -2 :
+                    case -1 :
+                        type = StackMapTableAttribute.CHOP_FRAME; // CHOP or FULL
+                        localsSize = clocalsSize; // for full_frame check
+                        break;
+
+                    case 0 :
+                        // SAME, SAME_EXTENDED or FULL
+                        type = delta < 64 ? StackMapTableAttribute.SAME_FRAME : StackMapTableAttribute.SAME_FRAME_EXTENDED;
+                        break;
+
+                    case 1 :
+                    case 2 :
+                    case 3 :
+                        type = StackMapTableAttribute.APPEND_FRAME; // APPEND or FULL
+                        break;
+                }
+            } else if ( localsSize == clocalsSize && cstackSize == 1 ) {
+                // SAME_LOCAL_1_STACK or FULL
+                type = delta < 63 ? StackMapTableAttribute.SAME_LOCALS_1_STACK_ITEM_FRAME : StackMapTableAttribute.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED;
+            }
+
+            if ( type != StackMapTableAttribute.FULL_FRAME ) {
+                // verify if stack and locals are the same
+                for ( int j = 0; j < localsSize && type != StackMapTableAttribute.FULL_FRAME; j++ ) {
+                    if ( !locals.get( j ).equals( clocals.get( j ) ) ) {
+                        type = StackMapTableAttribute.FULL_FRAME;
+                    }
+                }
+            }
+
+            switch ( type ) {
+                case SAME_FRAME :
+                    bv.putByte( delta );
+                    break;
+
+                case SAME_LOCALS_1_STACK_ITEM_FRAME :
+                    bv.putByte( StackMapTableAttribute.SAME_LOCALS_1_STACK_ITEM_FRAME + delta );
+                    writeTypeInfos( bv,
+                                    cw,
+                                    cstack,
+                                    0,
+                                    1 );
+                    break;
+
+                case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED :
+                    bv.putByte( StackMapTableAttribute.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED );
+                    writeSize( delta,
+                               bv,
+                               isExtCodeSize );
+                    writeTypeInfos( bv,
+                                    cw,
+                                    cstack,
+                                    0,
+                                    1 );
+                    break;
+
+                case SAME_FRAME_EXTENDED :
+                    bv.putByte( StackMapTableAttribute.SAME_FRAME_EXTENDED );
+                    writeSize( delta,
+                               bv,
+                               isExtCodeSize );
+                    break;
+
+                case CHOP_FRAME :
+                    bv.putByte( StackMapTableAttribute.SAME_FRAME_EXTENDED + k ); // negative k
+                    writeSize( delta,
+                               bv,
+                               isExtCodeSize );
+                    break;
+
+                case APPEND_FRAME :
+                    bv.putByte( StackMapTableAttribute.SAME_FRAME_EXTENDED + k ); // positive k
+                    writeSize( delta,
+                               bv,
+                               isExtCodeSize );
+                    writeTypeInfos( bv,
+                                    cw,
+                                    clocals,
+                                    clocalsSize - 1,
+                                    clocalsSize );
+                    break;
+
+                case FULL_FRAME :
+                    bv.putByte( StackMapTableAttribute.FULL_FRAME );
+                    writeSize( delta,
+                               bv,
+                               isExtCodeSize );
+                    writeSize( clocalsSize,
+                               bv,
+                               isExtLocals );
+                    writeTypeInfos( bv,
+                                    cw,
+                                    clocals,
+                                    0,
+                                    clocalsSize );
+                    writeSize( cstackSize,
+                               bv,
+                               isExtStack );
+                    writeTypeInfos( bv,
+                                    cw,
+                                    cstack,
+                                    0,
+                                    cstackSize );
+                    break;
+
+                default :
+                    throw new RuntimeException();
+            }
+            offset = coffset + 1; // compensating non first offset
+            locals = clocals;
+        }
+        return bv;
+    }
+
+    private void writeSize(final int delta,
+                           final ByteVector bv,
+                           final boolean isExt) {
+        if ( isExt ) {
+            bv.putInt( delta );
+        } else {
+            bv.putShort( delta );
+        }
+    }
+
+    private void writeTypeInfos(final ByteVector bv,
+                                final ClassWriter cw,
+                                final List info,
+                                final int start,
+                                final int end) {
+        for ( int j = start; j < end; j++ ) {
+            final StackMapType typeInfo = (StackMapType) info.get( j );
+            bv.putByte( typeInfo.getType() );
+
+            switch ( typeInfo.getType() ) {
+                case StackMapType.ITEM_Object : //
+                    bv.putShort( cw.newClass( typeInfo.getObject() ) );
+                    break;
+
+                case StackMapType.ITEM_Uninitialized : //
+                    bv.putShort( typeInfo.getLabel().getOffset() );
+                    break;
+
+            }
+        }
+    }
+
+    public static int getMethodOff(final ClassReader cr,
+                                   final int codeOff,
+                                   final char[] buf) {
+        int off = cr.header + 6;
+
+        final int interfacesCount = cr.readUnsignedShort( off );
+        off += 2 + interfacesCount * 2;
+
+        int fieldsCount = cr.readUnsignedShort( off );
+        off += 2;
+        for ( ; fieldsCount > 0; --fieldsCount ) {
+            int attrCount = cr.readUnsignedShort( off + 6 ); // field attributes
+            off += 8;
+            for ( ; attrCount > 0; --attrCount ) {
+                off += 6 + cr.readInt( off + 2 );
+            }
+        }
+
+        int methodsCount = cr.readUnsignedShort( off );
+        off += 2;
+        for ( ; methodsCount > 0; --methodsCount ) {
+            final int methodOff = off;
+            int attrCount = cr.readUnsignedShort( off + 6 ); // method attributes
+            off += 8;
+            for ( ; attrCount > 0; --attrCount ) {
+                final String attrName = cr.readUTF8( off,
+                                                     buf );
+                off += 6;
+                if ( attrName.equals( "Code" ) ) {
+                    if ( codeOff == off ) {
+                        return methodOff;
+                    }
+                }
+                off += cr.readInt( off - 4 );
+            }
+        }
+
+        return -1;
+    }
+
+    /**
+     * Use method signature and access flags to resolve initial locals state.
+     * 
+     * @param className name of the method's owner class.
+     * @param access access flags of the method.
+     * @param methodName name of the method.
+     * @param methodDesc descriptor of the method.
+     * @return list of <code>StackMapType</code> instances representing locals
+     *         for an initial frame.
+     */
+    public static List calculateLocals(final String className,
+                                       final int access,
+                                       final String methodName,
+                                       final String methodDesc) {
+        final List locals = new ArrayList();
+
+        // TODO
+        if ( "<init>".equals( methodName ) && !className.equals( "java/lang/Object" ) ) {
+            final StackMapType typeInfo = StackMapType.getTypeInfo( StackMapType.ITEM_UninitializedThis );
+            typeInfo.setObject( className ); // this
+            locals.add( typeInfo );
+        } else if ( (access & Opcodes.ACC_STATIC) == 0 ) {
+            final StackMapType typeInfo = StackMapType.getTypeInfo( StackMapType.ITEM_Object );
+            typeInfo.setObject( className ); // this
+            locals.add( typeInfo );
+        }
+
+        final Type[] types = Type.getArgumentTypes( methodDesc );
+        for ( int i = 0; i < types.length; i++ ) {
+            final Type t = types[i];
+            StackMapType smt;
+            switch ( t.getSort() ) {
+                case Type.LONG :
+                    smt = StackMapType.getTypeInfo( StackMapType.ITEM_Long );
+                    break;
+                case Type.DOUBLE :
+                    smt = StackMapType.getTypeInfo( StackMapType.ITEM_Double );
+                    break;
+
+                case Type.FLOAT :
+                    smt = StackMapType.getTypeInfo( StackMapType.ITEM_Float );
+                    break;
+
+                case Type.ARRAY :
+                case Type.OBJECT :
+                    smt = StackMapType.getTypeInfo( StackMapType.ITEM_Object );
+                    smt.setObject( t.getDescriptor() ); // TODO verify name
+                    break;
+
+                default :
+                    smt = StackMapType.getTypeInfo( StackMapType.ITEM_Integer );
+                    break;
+            }
+        }
+
+        return locals;
+    }
+
+    private int readTypes(final List info,
+                          final boolean isExt,
+                          final boolean isExtCodeSize,
+                          final ClassReader cr,
+                          int off,
+                          final Label[] labels,
+                          final char[] buf) {
+        int n = 0;
+        if ( isExt ) {
+            n = cr.readInt( off );
+            off += 4;
+        } else {
+            n = cr.readUnsignedShort( off );
+            off += 2;
+        }
+
+        for ( ; n > 0; n-- ) {
+            off = readType( info,
+                            isExtCodeSize,
+                            cr,
+                            off,
+                            labels,
+                            buf );
+        }
+        return off;
+    }
+
+    private int readType(final List info,
+                         final boolean isExtCodeSize,
+                         final ClassReader cr,
+                         int off,
+                         final Label[] labels,
+                         final char[] buf) {
+        final int itemType = cr.readByte( off++ );
+        final StackMapType typeInfo = StackMapType.getTypeInfo( itemType );
+        info.add( typeInfo );
+        switch ( itemType ) {
+            // case StackMapType.ITEM_Long: //
+            // case StackMapType.ITEM_Double: //
+            // info.add(StackMapType.getTypeInfo(StackMapType.ITEM_Top));
+            // break;
+
+            case StackMapType.ITEM_Object : //
+                typeInfo.setObject( cr.readClass( off,
+                                                  buf ) );
+                off += 2;
+                break;
+
+            case StackMapType.ITEM_Uninitialized : //
+                int offset;
+                if ( isExtCodeSize ) {
+                    offset = cr.readInt( off );
+                    off += 4;
+                } else {
+                    offset = cr.readUnsignedShort( off );
+                    off += 2;
+                }
+
+                typeInfo.setLabel( getLabel( offset,
+                                             labels ) );
+                break;
+        }
+        return off;
+    }
+
+    private Label getLabel(final int offset,
+                           final Label[] labels) {
+        final Label l = labels[offset];
+        if ( l != null ) {
+            return l;
+        }
+        return labels[offset] = new Label();
+    }
+
+    public String toString() {
+        final StringBuffer sb = new StringBuffer( "StackMapTable[" );
+        for ( int i = 0; i < this.frames.size(); i++ ) {
+            sb.append( '\n' ).append( '[' ).append( this.frames.get( i ) ).append( ']' );
+        }
+        sb.append( "\n]" );
+        return sb.toString();
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/attrs/StackMapType.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/attrs/StackMapType.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/attrs/StackMapType.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,105 @@
+/**
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.drools.asm.attrs;
+
+import org.drools.asm.Label;
+
+/**
+ * Verification type info used by {@link StackMapAttribute}.
+ * 
+ * @see <a href="http://www.jcp.org/en/jsr/detail?id=139">JSR 139 : Connected
+ *      Limited Device Configuration 1.1</a>
+ * 
+ * @see "ClassFileFormat-Java6.fm Page 138 Friday, April 15, 2005 3:22 PM"
+ * 
+ * @author Eugene Kuleshov
+ */
+
+public class StackMapType {
+
+    public static final int      ITEM_Top               = 0;
+    public static final int      ITEM_Integer           = 1;
+    public static final int      ITEM_Float             = 2;
+    public static final int      ITEM_Double            = 3;
+    public static final int      ITEM_Long              = 4;
+    public static final int      ITEM_Null              = 5;
+    public static final int      ITEM_UninitializedThis = 6;
+    public static final int      ITEM_Object            = 7;
+    public static final int      ITEM_Uninitialized     = 8;
+
+    public static final String[] ITEM_NAMES             = {"Top", "Integer", "Float", "Double", "Long", "Null", "UninitializedThis", "Object", "Uninitialized"};
+
+    private int                  type;
+    private Label                offset;
+    private String               object;
+
+    private StackMapType(final int type) {
+        this.type = type;
+    }
+
+    public int getType() {
+        return this.type;
+    }
+
+    public static StackMapType getTypeInfo(final int itemType) {
+        if ( itemType < StackMapType.ITEM_Top || itemType > StackMapType.ITEM_Uninitialized ) {
+            throw new IllegalArgumentException( "" + itemType );
+        }
+        return new StackMapType( itemType );
+    }
+
+    public void setLabel(final Label offset) {
+        this.offset = offset;
+    }
+
+    public void setObject(final String object) {
+        this.object = object;
+    }
+
+    public Label getLabel() {
+        return this.offset;
+    }
+
+    public String getObject() {
+        return this.object;
+    }
+
+    public String toString() {
+        final StringBuffer sb = new StringBuffer( StackMapType.ITEM_NAMES[this.type] );
+        if ( this.type == StackMapType.ITEM_Object ) {
+            sb.append( ":" ).append( this.object );
+        }
+        if ( this.type == StackMapType.ITEM_Uninitialized ) {
+            sb.append( ":L" ).append( System.identityHashCode( this.offset ) );
+        }
+        return sb.toString();
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/attrs/package.html
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/attrs/package.html	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/attrs/package.html	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,48 @@
+<html>
+<!--
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<body>
+Provides an implementation for optional class, field and method attributes.
+
+<p>
+
+By default ASM strips optional attributes, in order to keep them in
+the bytecode that is being readed you should pass an array of required attribute
+instances to {@link org.objectweb.asm.ClassReader#accept(org.objectweb.asm.ClassVisitor, org.objectweb.asm.Attribute[], boolean) ClassReader.accept()} method.
+In order to add custom attributes to the manually constructed bytecode concrete
+subclasses of the {@link org.objectweb.asm.Attribute Attribute} can be passed to 
+the visitAttribute methods of the 
+{@link org.objectweb.asm.ClassVisitor ClassVisitor}, 
+{@link org.objectweb.asm.FieldVisitor FieldVisitor} and
+{@link org.objectweb.asm.MethodVisitor MethodVisitor} interfaces.
+
+ at since ASM 1.4.1
+</body>
+</html>

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/AdviceAdapter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/AdviceAdapter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/AdviceAdapter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,670 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.commons;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.drools.asm.Label;
+import org.drools.asm.MethodVisitor;
+import org.drools.asm.Opcodes;
+import org.drools.asm.Type;
+
+/**
+ * A <code>MethodAdapter</code> to dispatch method body instruction
+ * <p>
+ * The behavior is like this:
+ * <ol>
+ * 
+ * <li>as long as the INVOKESPECIAL for the object initialization has not been
+ *     reached, every bytecode instruction is dispatched in the ctor code visitor</li>
+ * 
+ * <li>when this one is reached, it is only added in the ctor code visitor and
+ *     a JP invoke is added</li>
+ * <li>after that, only the other code visitor receives the instructions</li>
+ * 
+ * </ol>
+ * 
+ * @author Eugene Kuleshov
+ * @author Eric Bruneton
+ */
+public abstract class AdviceAdapter extends GeneratorAdapter
+    implements
+    Opcodes {
+    private static final Object THIS  = new Object();
+    private static final Object OTHER = new Object();
+
+    protected int               methodAccess;
+    protected String            methodDesc;
+
+    private boolean             constructor;
+    private boolean             superInitialized;
+    private ArrayList           stackFrame;
+    private HashMap             branches;
+
+    /**
+     * Creates a new {@link AdviceAdapter}.
+     * 
+     * @param mv the method visitor to which this adapter delegates calls.
+     * @param access the method's access flags (see {@link Opcodes}).
+     * @param name the method's name.
+     * @param desc the method's descriptor (see {@link Type Type}).
+     */
+    public AdviceAdapter(final MethodVisitor mv,
+                         final int access,
+                         final String name,
+                         final String desc) {
+        super( mv,
+               access,
+               name,
+               desc );
+        this.methodAccess = access;
+        this.methodDesc = desc;
+
+        this.constructor = "<init>".equals( name );
+        if ( !this.constructor ) {
+            this.superInitialized = true;
+            onMethodEnter();
+        } else {
+            this.stackFrame = new ArrayList();
+            this.branches = new HashMap();
+        }
+    }
+
+    public void visitLabel(final Label label) {
+        this.mv.visitLabel( label );
+
+        if ( this.constructor && this.branches != null ) {
+            final ArrayList frame = (ArrayList) this.branches.get( label );
+            if ( frame != null ) {
+                this.stackFrame = frame;
+                this.branches.remove( label );
+            }
+        }
+    }
+
+    public void visitInsn(final int opcode) {
+        if ( this.constructor ) {
+            switch ( opcode ) {
+                case RETURN : // empty stack
+                    onMethodExit( opcode );
+                    break;
+
+                case IRETURN : // 1 before n/a after
+                case FRETURN : // 1 before n/a after
+                case ARETURN : // 1 before n/a after
+                case ATHROW : // 1 before n/a after
+                    popValue();
+                    popValue();
+                    onMethodExit( opcode );
+                    break;
+
+                case LRETURN : // 2 before n/a after
+                case DRETURN : // 2 before n/a after
+                    popValue();
+                    popValue();
+                    onMethodExit( opcode );
+                    break;
+
+                case NOP :
+                case LALOAD : // remove 2 add 2
+                case DALOAD : // remove 2 add 2
+                case LNEG :
+                case DNEG :
+                case FNEG :
+                case INEG :
+                case L2D :
+                case D2L :
+                case F2I :
+                case I2B :
+                case I2C :
+                case I2S :
+                case I2F :
+                case Opcodes.ARRAYLENGTH :
+                    break;
+
+                case ACONST_NULL :
+                case ICONST_M1 :
+                case ICONST_0 :
+                case ICONST_1 :
+                case ICONST_2 :
+                case ICONST_3 :
+                case ICONST_4 :
+                case ICONST_5 :
+                case FCONST_0 :
+                case FCONST_1 :
+                case FCONST_2 :
+                case F2L : // 1 before 2 after
+                case F2D :
+                case I2L :
+                case I2D :
+                    pushValue( AdviceAdapter.OTHER );
+                    break;
+
+                case LCONST_0 :
+                case LCONST_1 :
+                case DCONST_0 :
+                case DCONST_1 :
+                    pushValue( AdviceAdapter.OTHER );
+                    pushValue( AdviceAdapter.OTHER );
+                    break;
+
+                case IALOAD : // remove 2 add 1
+                case FALOAD : // remove 2 add 1
+                case AALOAD : // remove 2 add 1
+                case BALOAD : // remove 2 add 1
+                case CALOAD : // remove 2 add 1
+                case SALOAD : // remove 2 add 1
+                case POP :
+                case IADD :
+                case FADD :
+                case ISUB :
+                case LSHL : // 3 before 2 after
+                case LSHR : // 3 before 2 after
+                case LUSHR : // 3 before 2 after
+                case L2I : // 2 before 1 after
+                case L2F : // 2 before 1 after
+                case D2I : // 2 before 1 after
+                case D2F : // 2 before 1 after
+                case FSUB :
+                case FMUL :
+                case FDIV :
+                case FREM :
+                case FCMPL : // 2 before 1 after
+                case FCMPG : // 2 before 1 after
+                case IMUL :
+                case IDIV :
+                case IREM :
+                case ISHL :
+                case ISHR :
+                case IUSHR :
+                case IAND :
+                case IOR :
+                case IXOR :
+                case MONITORENTER :
+                case MONITOREXIT :
+                    popValue();
+                    break;
+
+                case POP2 :
+                case LSUB :
+                case LMUL :
+                case LDIV :
+                case LREM :
+                case LADD :
+                case LAND :
+                case LOR :
+                case LXOR :
+                case DADD :
+                case DMUL :
+                case DSUB :
+                case DDIV :
+                case DREM :
+                    popValue();
+                    popValue();
+                    break;
+
+                case IASTORE :
+                case FASTORE :
+                case AASTORE :
+                case BASTORE :
+                case CASTORE :
+                case SASTORE :
+                case LCMP : // 4 before 1 after
+                case DCMPL :
+                case DCMPG :
+                    popValue();
+                    popValue();
+                    popValue();
+                    break;
+
+                case LASTORE :
+                case DASTORE :
+                    popValue();
+                    popValue();
+                    popValue();
+                    popValue();
+                    break;
+
+                case DUP :
+                    pushValue( peekValue() );
+                    break;
+
+                case DUP_X1 :
+                    // TODO optimize this
+                {
+                    final Object o1 = popValue();
+                    final Object o2 = popValue();
+                    pushValue( o1 );
+                    pushValue( o2 );
+                    pushValue( o1 );
+                }
+                    break;
+
+                case DUP_X2 :
+                    // TODO optimize this
+                {
+                    final Object o1 = popValue();
+                    final Object o2 = popValue();
+                    final Object o3 = popValue();
+                    pushValue( o1 );
+                    pushValue( o3 );
+                    pushValue( o2 );
+                    pushValue( o1 );
+                }
+                    break;
+
+                case DUP2 :
+                    // TODO optimize this
+                {
+                    final Object o1 = popValue();
+                    final Object o2 = popValue();
+                    pushValue( o2 );
+                    pushValue( o1 );
+                    pushValue( o2 );
+                    pushValue( o1 );
+                }
+                    break;
+
+                case DUP2_X1 :
+                    // TODO optimize this
+                {
+                    final Object o1 = popValue();
+                    final Object o2 = popValue();
+                    final Object o3 = popValue();
+                    pushValue( o2 );
+                    pushValue( o1 );
+                    pushValue( o3 );
+                    pushValue( o2 );
+                    pushValue( o1 );
+                }
+                    break;
+
+                case DUP2_X2 :
+                    // TODO optimize this
+                {
+                    final Object o1 = popValue();
+                    final Object o2 = popValue();
+                    final Object o3 = popValue();
+                    final Object o4 = popValue();
+                    pushValue( o2 );
+                    pushValue( o1 );
+                    pushValue( o4 );
+                    pushValue( o3 );
+                    pushValue( o2 );
+                    pushValue( o1 );
+                }
+                    break;
+
+                case SWAP : {
+                    final Object o1 = popValue();
+                    final Object o2 = popValue();
+                    pushValue( o1 );
+                    pushValue( o2 );
+                }
+                    break;
+            }
+        } else {
+            switch ( opcode ) {
+                case RETURN :
+                case IRETURN :
+                case FRETURN :
+                case ARETURN :
+                case LRETURN :
+                case DRETURN :
+                case ATHROW :
+                    onMethodExit( opcode );
+                    break;
+            }
+        }
+        this.mv.visitInsn( opcode );
+    }
+
+    public void visitVarInsn(final int opcode,
+                             final int var) {
+        super.visitVarInsn( opcode,
+                            var );
+
+        if ( this.constructor ) {
+            switch ( opcode ) {
+                case ILOAD :
+                case FLOAD :
+                    pushValue( AdviceAdapter.OTHER );
+                    break;
+                case LLOAD :
+                case DLOAD :
+                    pushValue( AdviceAdapter.OTHER );
+                    pushValue( AdviceAdapter.OTHER );
+                    break;
+                case ALOAD :
+                    pushValue( var == 0 ? AdviceAdapter.THIS : AdviceAdapter.OTHER );
+                    break;
+                case ASTORE :
+                case ISTORE :
+                case FSTORE :
+                    popValue();
+                    break;
+                case LSTORE :
+                case DSTORE :
+                    popValue();
+                    popValue();
+                    break;
+            }
+        }
+    }
+
+    public void visitFieldInsn(final int opcode,
+                               final String owner,
+                               final String name,
+                               final String desc) {
+        this.mv.visitFieldInsn( opcode,
+                                owner,
+                                name,
+                                desc );
+
+        if ( this.constructor ) {
+            final char c = desc.charAt( 0 );
+            final boolean longOrDouble = c == 'J' || c == 'D';
+            switch ( opcode ) {
+                case GETSTATIC :
+                    pushValue( AdviceAdapter.OTHER );
+                    if ( longOrDouble ) {
+                        pushValue( AdviceAdapter.OTHER );
+                    }
+                    break;
+                case PUTSTATIC :
+                    popValue();
+                    if ( longOrDouble ) {
+                        popValue();
+                    }
+                    break;
+                case PUTFIELD :
+                    popValue();
+                    if ( longOrDouble ) {
+                        popValue();
+                        popValue();
+                    }
+                    break;
+                // case GETFIELD:
+                default :
+                    if ( longOrDouble ) {
+                        pushValue( AdviceAdapter.OTHER );
+                    }
+            }
+        }
+    }
+
+    public void visitIntInsn(final int opcode,
+                             final int operand) {
+        this.mv.visitIntInsn( opcode,
+                              operand );
+
+        if ( this.constructor ) {
+            switch ( opcode ) {
+                case BIPUSH :
+                case SIPUSH :
+                    pushValue( AdviceAdapter.OTHER );
+            }
+        }
+    }
+
+    public void visitLdcInsn(final Object cst) {
+        this.mv.visitLdcInsn( cst );
+
+        if ( this.constructor ) {
+            pushValue( AdviceAdapter.OTHER );
+            if ( cst instanceof Double || cst instanceof Long ) {
+                pushValue( AdviceAdapter.OTHER );
+            }
+        }
+    }
+
+    public void visitMultiANewArrayInsn(final String desc,
+                                        final int dims) {
+        this.mv.visitMultiANewArrayInsn( desc,
+                                         dims );
+
+        if ( this.constructor ) {
+            for ( int i = 0; i < dims; i++ ) {
+                popValue();
+            }
+            pushValue( AdviceAdapter.OTHER );
+        }
+    }
+
+    public void visitTypeInsn(final int opcode,
+                              final String name) {
+        this.mv.visitTypeInsn( opcode,
+                               name );
+
+        // ANEWARRAY, CHECKCAST or INSTANCEOF don't change stack
+        if ( this.constructor && opcode == Opcodes.NEW ) {
+            pushValue( AdviceAdapter.OTHER );
+        }
+    }
+
+    public void visitMethodInsn(final int opcode,
+                                final String owner,
+                                final String name,
+                                final String desc) {
+        this.mv.visitMethodInsn( opcode,
+                                 owner,
+                                 name,
+                                 desc );
+
+        if ( this.constructor ) {
+            final Type[] types = Type.getArgumentTypes( desc );
+            for ( int i = 0; i < types.length; i++ ) {
+                popValue();
+                if ( types[i].getSize() == 2 ) {
+                    popValue();
+                }
+            }
+            switch ( opcode ) {
+                // case INVOKESTATIC:
+                // break;
+
+                case INVOKEINTERFACE :
+                case INVOKEVIRTUAL :
+                    popValue(); // objectref
+                    break;
+
+                case INVOKESPECIAL :
+                    final Object type = popValue(); // objectref
+                    if ( type == AdviceAdapter.THIS && !this.superInitialized ) {
+                        onMethodEnter();
+                        this.superInitialized = true;
+                        // once super has been initialized it is no longer 
+                        // necessary to keep track of stack state                        
+                        this.constructor = false;
+                    }
+                    break;
+            }
+
+            final Type returnType = Type.getReturnType( desc );
+            if ( returnType != Type.VOID_TYPE ) {
+                pushValue( AdviceAdapter.OTHER );
+                if ( returnType.getSize() == 2 ) {
+                    pushValue( AdviceAdapter.OTHER );
+                }
+            }
+        }
+    }
+
+    public void visitJumpInsn(final int opcode,
+                              final Label label) {
+        this.mv.visitJumpInsn( opcode,
+                               label );
+
+        if ( this.constructor ) {
+            switch ( opcode ) {
+                case IFEQ :
+                case IFNE :
+                case IFLT :
+                case IFGE :
+                case IFGT :
+                case IFLE :
+                case IFNULL :
+                case IFNONNULL :
+                    popValue();
+                    break;
+
+                case IF_ICMPEQ :
+                case IF_ICMPNE :
+                case IF_ICMPLT :
+                case IF_ICMPGE :
+                case IF_ICMPGT :
+                case IF_ICMPLE :
+                case IF_ACMPEQ :
+                case IF_ACMPNE :
+                    popValue();
+                    popValue();
+                    break;
+
+                case JSR :
+                    pushValue( AdviceAdapter.OTHER );
+                    break;
+            }
+            addBranch( label );
+        }
+    }
+
+    public void visitLookupSwitchInsn(final Label dflt,
+                                      final int[] keys,
+                                      final Label[] labels) {
+        this.mv.visitLookupSwitchInsn( dflt,
+                                       keys,
+                                       labels );
+
+        if ( this.constructor ) {
+            popValue();
+            addBranches( dflt,
+                         labels );
+        }
+    }
+
+    public void visitTableSwitchInsn(final int min,
+                                     final int max,
+                                     final Label dflt,
+                                     final Label[] labels) {
+        this.mv.visitTableSwitchInsn( min,
+                                      max,
+                                      dflt,
+                                      labels );
+
+        if ( this.constructor ) {
+            popValue();
+            addBranches( dflt,
+                         labels );
+        }
+    }
+
+    private void addBranches(final Label dflt,
+                             final Label[] labels) {
+        addBranch( dflt );
+        for ( int i = 0; i < labels.length; i++ ) {
+            addBranch( labels[i] );
+        }
+    }
+
+    private void addBranch(final Label label) {
+        if ( this.branches.containsKey( label ) ) {
+            return;
+        }
+        final ArrayList frame = new ArrayList();
+        frame.addAll( this.stackFrame );
+        this.branches.put( label,
+                           frame );
+    }
+
+    private Object popValue() {
+        return this.stackFrame.remove( this.stackFrame.size() - 1 );
+    }
+
+    private Object peekValue() {
+        return this.stackFrame.get( this.stackFrame.size() - 1 );
+    }
+
+    private void pushValue(final Object o) {
+        this.stackFrame.add( o );
+    }
+
+    /**
+     * Called at the beginning of the method or after super 
+     * class class call in the constructor.
+     * <br><br>
+     * 
+     * <i>Custom code can use or change all the local variables,
+     * but should not change state of the stack.</i>
+     */
+    protected abstract void onMethodEnter();
+
+    /**
+     * Called before explicit exit from the method using either
+     * return or throw. Top element on the stack contains the 
+     * return value or exception instance. For example:
+     * 
+     * <pre>
+     *   public void onMethodExit(int opcode) {
+     *     if(opcode==RETURN) {
+     *         visitInsn(ACONST_NULL);
+     *     } else if(opcode==ARETURN || opcode==ATHROW) {
+     *         dup();
+     *     } else {
+     *         if(opcode==LRETURN || opcode==DRETURN) {
+     *             dup2();
+     *         } else {
+     *             dup();
+     *         }
+     *         box(Type.getReturnType(this.methodDesc));
+     *     }
+     *     visitIntInsn(SIPUSH, opcode);
+     *     visitMethodInsn(INVOKESTATIC, owner, "onExit", "(Ljava/lang/Object;I)V");
+     *   }
+     *
+     *   // an actual call back method
+     *   public static void onExit(int opcode, Object param) {
+     *     ...
+     * </pre>
+     * 
+     * <br><br>
+     * 
+     * <i>Custom code can use or change all the local variables,
+     * but should not change state of the stack.</i>
+     * 
+     * @param opcode one of the RETURN, IRETURN, FRETURN, 
+     *   ARETURN, LRETURN, DRETURN or ATHROW
+     * 
+     */
+    protected abstract void onMethodExit(int opcode);
+
+    // TODO onException, onMethodCall
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/EmptyVisitor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/EmptyVisitor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/EmptyVisitor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,209 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.commons;
+
+import org.drools.asm.AnnotationVisitor;
+import org.drools.asm.Attribute;
+import org.drools.asm.ClassVisitor;
+import org.drools.asm.FieldVisitor;
+import org.drools.asm.Label;
+import org.drools.asm.MethodVisitor;
+
+/**
+ * An empty implementation of the ASM visitor interfaces.
+ * 
+ * @author Eric Bruneton
+ */
+public class EmptyVisitor
+    implements
+    ClassVisitor,
+    FieldVisitor,
+    MethodVisitor,
+    AnnotationVisitor {
+
+    public void visit(final int version,
+                      final int access,
+                      final String name,
+                      final String signature,
+                      final String superName,
+                      final String[] interfaces) {
+    }
+
+    public void visitSource(final String source,
+                            final String debug) {
+    }
+
+    public void visitOuterClass(final String owner,
+                                final String name,
+                                final String desc) {
+    }
+
+    public AnnotationVisitor visitAnnotation(final String desc,
+                                             final boolean visible) {
+        return this;
+    }
+
+    public void visitAttribute(final Attribute attr) {
+    }
+
+    public void visitInnerClass(final String name,
+                                final String outerName,
+                                final String innerName,
+                                final int access) {
+    }
+
+    public FieldVisitor visitField(final int access,
+                                   final String name,
+                                   final String desc,
+                                   final String signature,
+                                   final Object value) {
+        return this;
+    }
+
+    public MethodVisitor visitMethod(final int access,
+                                     final String name,
+                                     final String desc,
+                                     final String signature,
+                                     final String[] exceptions) {
+        return this;
+    }
+
+    public void visitEnd() {
+    }
+
+    public AnnotationVisitor visitAnnotationDefault() {
+        return this;
+    }
+
+    public AnnotationVisitor visitParameterAnnotation(final int parameter,
+                                                      final String desc,
+                                                      final boolean visible) {
+        return this;
+    }
+
+    public void visitCode() {
+    }
+
+    public void visitInsn(final int opcode) {
+    }
+
+    public void visitIntInsn(final int opcode,
+                             final int operand) {
+    }
+
+    public void visitVarInsn(final int opcode,
+                             final int var) {
+    }
+
+    public void visitTypeInsn(final int opcode,
+                              final String desc) {
+    }
+
+    public void visitFieldInsn(final int opcode,
+                               final String owner,
+                               final String name,
+                               final String desc) {
+    }
+
+    public void visitMethodInsn(final int opcode,
+                                final String owner,
+                                final String name,
+                                final String desc) {
+    }
+
+    public void visitJumpInsn(final int opcode,
+                              final Label label) {
+    }
+
+    public void visitLabel(final Label label) {
+    }
+
+    public void visitLdcInsn(final Object cst) {
+    }
+
+    public void visitIincInsn(final int var,
+                              final int increment) {
+    }
+
+    public void visitTableSwitchInsn(final int min,
+                                     final int max,
+                                     final Label dflt,
+                                     final Label labels[]) {
+    }
+
+    public void visitLookupSwitchInsn(final Label dflt,
+                                      final int keys[],
+                                      final Label labels[]) {
+    }
+
+    public void visitMultiANewArrayInsn(final String desc,
+                                        final int dims) {
+    }
+
+    public void visitTryCatchBlock(final Label start,
+                                   final Label end,
+                                   final Label handler,
+                                   final String type) {
+    }
+
+    public void visitLocalVariable(final String name,
+                                   final String desc,
+                                   final String signature,
+                                   final Label start,
+                                   final Label end,
+                                   final int index) {
+    }
+
+    public void visitLineNumber(final int line,
+                                final Label start) {
+    }
+
+    public void visitMaxs(final int maxStack,
+                          final int maxLocals) {
+    }
+
+    public void visit(final String name,
+                      final Object value) {
+    }
+
+    public void visitEnum(final String name,
+                          final String desc,
+                          final String value) {
+    }
+
+    public AnnotationVisitor visitAnnotation(final String name,
+                                             final String desc) {
+        return this;
+    }
+
+    public AnnotationVisitor visitArray(final String name) {
+        return this;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/GeneratorAdapter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/GeneratorAdapter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/GeneratorAdapter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,1542 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.commons;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.drools.asm.ClassVisitor;
+import org.drools.asm.Label;
+import org.drools.asm.MethodVisitor;
+import org.drools.asm.Opcodes;
+import org.drools.asm.Type;
+
+/**
+ * A {@link org.drools.asm.MethodAdapter} with convenient methods to generate
+ * code. For example, using this adapter, the class below
+ * 
+ * <pre>
+ * public class Example {
+ *     public static void main(String[] args) {
+ *         System.out.println(&quot;Hello world!&quot;);
+ *     }
+ * }
+ * </pre>
+ * 
+ * can be generated as follows:
+ * 
+ * <pre>
+ * ClassWriter cw = new ClassWriter(true);
+ * cw.visit(V1_1, ACC_PUBLIC, &quot;Example&quot;, null, &quot;java/lang/Object&quot;, null);
+ * 
+ * Method m = Method.getMethod(&quot;void &lt;init&gt; ()&quot;);
+ * GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null, cw);
+ * mg.loadThis();
+ * mg.invokeConstructor(Type.getType(Object.class), m);
+ * mg.returnValue();
+ * mg.endMethod();
+ * 
+ * m = Method.getMethod(&quot;void main (String[])&quot;);
+ * mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw);
+ * mg.getStatic(Type.getType(System.class), &quot;out&quot;, Type.getType(PrintStream.class));
+ * mg.push(&quot;Hello world!&quot;);
+ * mg.invokeVirtual(Type.getType(PrintStream.class), Method.getMethod(&quot;void println (String)&quot;));
+ * mg.returnValue();
+ * mg.endMethod();
+ * 
+ * cw.visitEnd();
+ * </pre>
+ * 
+ * @author Juozas Baliuka
+ * @author Chris Nokleberg
+ * @author Eric Bruneton
+ */
+public class GeneratorAdapter extends LocalVariablesSorter {
+
+    private final static Type   BYTE_TYPE      = Type.getType( "Ljava/lang/Byte;" );
+
+    private final static Type   BOOLEAN_TYPE   = Type.getType( "Ljava/lang/Boolean;" );
+
+    private final static Type   SHORT_TYPE     = Type.getType( "Ljava/lang/Short;" );
+
+    private final static Type   CHARACTER_TYPE = Type.getType( "Ljava/lang/Character;" );
+
+    private final static Type   INTEGER_TYPE   = Type.getType( "Ljava/lang/Integer;" );
+
+    private final static Type   FLOAT_TYPE     = Type.getType( "Ljava/lang/Float;" );
+
+    private final static Type   LONG_TYPE      = Type.getType( "Ljava/lang/Long;" );
+
+    private final static Type   DOUBLE_TYPE    = Type.getType( "Ljava/lang/Double;" );
+
+    private final static Type   NUMBER_TYPE    = Type.getType( "Ljava/lang/Number;" );
+
+    private final static Type   OBJECT_TYPE    = Type.getType( "Ljava/lang/Object;" );
+
+    private final static Method BOOLEAN_VALUE  = Method.getMethod( "boolean booleanValue()" );
+
+    private final static Method CHAR_VALUE     = Method.getMethod( "char charValue()" );
+
+    private final static Method INT_VALUE      = Method.getMethod( "int intValue()" );
+
+    private final static Method FLOAT_VALUE    = Method.getMethod( "float floatValue()" );
+
+    private final static Method LONG_VALUE     = Method.getMethod( "long longValue()" );
+
+    private final static Method DOUBLE_VALUE   = Method.getMethod( "double doubleValue()" );
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public final static int     ADD            = Opcodes.IADD;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public final static int     SUB            = Opcodes.ISUB;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public final static int     MUL            = Opcodes.IMUL;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public final static int     DIV            = Opcodes.IDIV;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public final static int     REM            = Opcodes.IREM;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public final static int     NEG            = Opcodes.INEG;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public final static int     SHL            = Opcodes.ISHL;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public final static int     SHR            = Opcodes.ISHR;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public final static int     USHR           = Opcodes.IUSHR;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public final static int     AND            = Opcodes.IAND;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public final static int     OR             = Opcodes.IOR;
+
+    /**
+     * Constant for the {@link #math math} method.
+     */
+    public final static int     XOR            = Opcodes.IXOR;
+
+    /**
+     * Constant for the {@link #ifCmp ifCmp} method.
+     */
+    public final static int     EQ             = Opcodes.IFEQ;
+
+    /**
+     * Constant for the {@link #ifCmp ifCmp} method.
+     */
+    public final static int     NE             = Opcodes.IFNE;
+
+    /**
+     * Constant for the {@link #ifCmp ifCmp} method.
+     */
+    public final static int     LT             = Opcodes.IFLT;
+
+    /**
+     * Constant for the {@link #ifCmp ifCmp} method.
+     */
+    public final static int     GE             = Opcodes.IFGE;
+
+    /**
+     * Constant for the {@link #ifCmp ifCmp} method.
+     */
+    public final static int     GT             = Opcodes.IFGT;
+
+    /**
+     * Constant for the {@link #ifCmp ifCmp} method.
+     */
+    public final static int     LE             = Opcodes.IFLE;
+
+    /**
+     * Access flags of the method visited by this adapter.
+     */
+    private final int           access;
+
+    /**
+     * Return type of the method visited by this adapter.
+     */
+    private final Type          returnType;
+
+    /**
+     * Argument types of the method visited by this adapter.
+     */
+    private final Type[]        argumentTypes;
+
+    /**
+     * Types of the local variables of the method visited by this adapter.
+     */
+    private final List          localTypes;
+
+    /**
+     * Creates a new {@link GeneratorAdapter}.
+     * 
+     * @param mv the method visitor to which this adapter delegates calls.
+     * @param access the method's access flags (see {@link Opcodes}).
+     * @param name the method's name.
+     * @param desc the method's descriptor (see {@link Type Type}).
+     */
+    public GeneratorAdapter(final MethodVisitor mv,
+                            final int access,
+                            final String name,
+                            final String desc) {
+        super( access,
+               desc,
+               mv );
+        this.access = access;
+        this.returnType = Type.getReturnType( desc );
+        this.argumentTypes = Type.getArgumentTypes( desc );
+        this.localTypes = new ArrayList();
+    }
+
+    /**
+     * Creates a new {@link GeneratorAdapter}.
+     * 
+     * @param access access flags of the adapted method.
+     * @param method the adapted method.
+     * @param mv the method visitor to which this adapter delegates calls.
+     */
+    public GeneratorAdapter(final int access,
+                            final Method method,
+                            final MethodVisitor mv) {
+        super( access,
+               method.getDescriptor(),
+               mv );
+        this.access = access;
+        this.returnType = method.getReturnType();
+        this.argumentTypes = method.getArgumentTypes();
+        this.localTypes = new ArrayList();
+    }
+
+    /**
+     * Creates a new {@link GeneratorAdapter}.
+     * 
+     * @param access access flags of the adapted method.
+     * @param method the adapted method.
+     * @param signature the signature of the adapted method (may be
+     *        <tt>null</tt>).
+     * @param exceptions the exceptions thrown by the adapted method (may be
+     *        <tt>null</tt>).
+     * @param cv the class visitor to which this adapter delegates calls.
+     */
+    public GeneratorAdapter(final int access,
+                            final Method method,
+                            final String signature,
+                            final Type[] exceptions,
+                            final ClassVisitor cv) {
+        this( access,
+              method,
+              cv.visitMethod( access,
+                              method.getName(),
+                              method.getDescriptor(),
+                              signature,
+                              getInternalNames( exceptions ) ) );
+    }
+
+    /**
+     * Returns the internal names of the given types.
+     * 
+     * @param types a set of types.
+     * @return the internal names of the given types.
+     */
+    private static String[] getInternalNames(final Type[] types) {
+        if ( types == null ) {
+            return null;
+        }
+        final String[] names = new String[types.length];
+        for ( int i = 0; i < names.length; ++i ) {
+            names[i] = types[i].getInternalName();
+        }
+        return names;
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to push constants on the stack
+    // ------------------------------------------------------------------------
+
+    /**
+     * Generates the instruction to push the given value on the stack.
+     * 
+     * @param value the value to be pushed on the stack.
+     */
+    public void push(final boolean value) {
+        push( value ? 1 : 0 );
+    }
+
+    /**
+     * Generates the instruction to push the given value on the stack.
+     * 
+     * @param value the value to be pushed on the stack.
+     */
+    public void push(final int value) {
+        if ( value >= -1 && value <= 5 ) {
+            this.mv.visitInsn( Opcodes.ICONST_0 + value );
+        } else if ( value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE ) {
+            this.mv.visitIntInsn( Opcodes.BIPUSH,
+                                  value );
+        } else if ( value >= Short.MIN_VALUE && value <= Short.MAX_VALUE ) {
+            this.mv.visitIntInsn( Opcodes.SIPUSH,
+                                  value );
+        } else {
+            this.mv.visitLdcInsn( new Integer( value ) );
+        }
+    }
+
+    /**
+     * Generates the instruction to push the given value on the stack.
+     * 
+     * @param value the value to be pushed on the stack.
+     */
+    public void push(final long value) {
+        if ( value == 0L || value == 1L ) {
+            this.mv.visitInsn( Opcodes.LCONST_0 + (int) value );
+        } else {
+            this.mv.visitLdcInsn( new Long( value ) );
+        }
+    }
+
+    /**
+     * Generates the instruction to push the given value on the stack.
+     * 
+     * @param value the value to be pushed on the stack.
+     */
+    public void push(final float value) {
+        final int bits = Float.floatToIntBits( value );
+        if ( bits == 0L || bits == 0x3f800000 || bits == 0x40000000 ) { // 0..2
+            this.mv.visitInsn( Opcodes.FCONST_0 + (int) value );
+        } else {
+            this.mv.visitLdcInsn( new Float( value ) );
+        }
+    }
+
+    /**
+     * Generates the instruction to push the given value on the stack.
+     * 
+     * @param value the value to be pushed on the stack.
+     */
+    public void push(final double value) {
+        final long bits = Double.doubleToLongBits( value );
+        if ( bits == 0L || bits == 0x3ff0000000000000L ) { // +0.0d and 1.0d
+            this.mv.visitInsn( Opcodes.DCONST_0 + (int) value );
+        } else {
+            this.mv.visitLdcInsn( new Double( value ) );
+        }
+    }
+
+    /**
+     * Generates the instruction to push the given value on the stack.
+     * 
+     * @param value the value to be pushed on the stack. May be <tt>null</tt>.
+     */
+    public void push(final String value) {
+        if ( value == null ) {
+            this.mv.visitInsn( Opcodes.ACONST_NULL );
+        } else {
+            this.mv.visitLdcInsn( value );
+        }
+    }
+
+    /**
+     * Generates the instruction to push the given value on the stack.
+     * 
+     * @param value the value to be pushed on the stack.
+     */
+    public void push(final Type value) {
+        if ( value == null ) {
+            this.mv.visitInsn( Opcodes.ACONST_NULL );
+        } else {
+            this.mv.visitLdcInsn( value );
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to load and store method arguments
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns the index of the given method argument in the frame's local
+     * variables array.
+     * 
+     * @param arg the index of a method argument.
+     * @return the index of the given method argument in the frame's local
+     *         variables array.
+     */
+    private int getArgIndex(final int arg) {
+        int index = ((this.access & Opcodes.ACC_STATIC) == 0 ? 1 : 0);
+        for ( int i = 0; i < arg; i++ ) {
+            index += this.argumentTypes[i].getSize();
+        }
+        return index;
+    }
+
+    /**
+     * Generates the instruction to push a local variable on the stack.
+     * 
+     * @param type the type of the local variable to be loaded.
+     * @param index an index in the frame's local variables array.
+     */
+    private void loadInsn(final Type type,
+                          final int index) {
+        this.mv.visitVarInsn( type.getOpcode( Opcodes.ILOAD ),
+                              index );
+    }
+
+    /**
+     * Generates the instruction to store the top stack value in a local
+     * variable.
+     * 
+     * @param type the type of the local variable to be stored.
+     * @param index an index in the frame's local variables array.
+     */
+    private void storeInsn(final Type type,
+                           final int index) {
+        this.mv.visitVarInsn( type.getOpcode( Opcodes.ISTORE ),
+                              index );
+    }
+
+    /**
+     * Generates the instruction to load 'this' on the stack.
+     */
+    public void loadThis() {
+        if ( (this.access & Opcodes.ACC_STATIC) != 0 ) {
+            throw new IllegalStateException( "no 'this' pointer within static method" );
+        }
+        this.mv.visitVarInsn( Opcodes.ALOAD,
+                              0 );
+    }
+
+    /**
+     * Generates the instruction to load the given method argument on the stack.
+     * 
+     * @param arg the index of a method argument.
+     */
+    public void loadArg(final int arg) {
+        loadInsn( this.argumentTypes[arg],
+                  getArgIndex( arg ) );
+    }
+
+    /**
+     * Generates the instructions to load the given method arguments on the
+     * stack.
+     * 
+     * @param arg the index of the first method argument to be loaded.
+     * @param count the number of method arguments to be loaded.
+     */
+    public void loadArgs(final int arg,
+                         final int count) {
+        int index = getArgIndex( arg );
+        for ( int i = 0; i < count; ++i ) {
+            final Type t = this.argumentTypes[arg + i];
+            loadInsn( t,
+                      index );
+            index += t.getSize();
+        }
+    }
+
+    /**
+     * Generates the instructions to load all the method arguments on the stack.
+     */
+    public void loadArgs() {
+        loadArgs( 0,
+                  this.argumentTypes.length );
+    }
+
+    /**
+     * Generates the instructions to load all the method arguments on the stack,
+     * as a single object array.
+     */
+    public void loadArgArray() {
+        push( this.argumentTypes.length );
+        newArray( GeneratorAdapter.OBJECT_TYPE );
+        for ( int i = 0; i < this.argumentTypes.length; i++ ) {
+            dup();
+            push( i );
+            loadArg( i );
+            box( this.argumentTypes[i] );
+            arrayStore( GeneratorAdapter.OBJECT_TYPE );
+        }
+    }
+
+    /**
+     * Generates the instruction to store the top stack value in the given
+     * method argument.
+     * 
+     * @param arg the index of a method argument.
+     */
+    public void storeArg(final int arg) {
+        storeInsn( this.argumentTypes[arg],
+                   getArgIndex( arg ) );
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to load and store local variables
+    // ------------------------------------------------------------------------
+
+    /**
+     * Creates a new local variable of the given type.
+     * 
+     * @param type the type of the local variable to be created.
+     * @return the identifier of the newly created local variable.
+     */
+    public int newLocal(final Type type) {
+        final int local = super.newLocal( type.getSize() );
+        setLocalType( local,
+                      type );
+        return local;
+    }
+
+    /**
+     * Returns the type of the given local variable.
+     * 
+     * @param local a local variable identifier, as returned by {@link #newLocal
+     *        newLocal}.
+     * @return the type of the given local variable.
+     */
+    public Type getLocalType(final int local) {
+        return (Type) this.localTypes.get( local - this.firstLocal );
+    }
+
+    /**
+     * Sets the current type of the given local variable.
+     * 
+     * @param local a local variable identifier, as returned by {@link #newLocal
+     *        newLocal}.
+     * @param type the type of the value being stored in the local variable
+     */
+    private void setLocalType(final int local,
+                              final Type type) {
+        final int index = local - this.firstLocal;
+        while ( this.localTypes.size() < index + 1 ) {
+            this.localTypes.add( null );
+        }
+        this.localTypes.set( index,
+                             type );
+    }
+
+    /**
+     * Generates the instruction to load the given local variable on the stack.
+     * 
+     * @param local a local variable identifier, as returned by {@link #newLocal
+     *        newLocal}.
+     */
+    public void loadLocal(final int local) {
+        loadInsn( getLocalType( local ),
+                  local );
+    }
+
+    /**
+     * Generates the instruction to load the given local variable on the stack.
+     * 
+     * @param local a local variable identifier, as returned by {@link #newLocal
+     *        newLocal}.
+     * @param type the type of this local variable.
+     */
+    public void loadLocal(final int local,
+                          final Type type) {
+        setLocalType( local,
+                      type );
+        loadInsn( type,
+                  local );
+    }
+
+    /**
+     * Generates the instruction to store the top stack value in the given local
+     * variable.
+     * 
+     * @param local a local variable identifier, as returned by {@link #newLocal
+     *        newLocal}.
+     */
+    public void storeLocal(final int local) {
+        storeInsn( getLocalType( local ),
+                   local );
+    }
+
+    /**
+     * Generates the instruction to store the top stack value in the given local
+     * variable.
+     * 
+     * @param local a local variable identifier, as returned by {@link #newLocal
+     *        newLocal}.
+     * @param type the type of this local variable.
+     */
+    public void storeLocal(final int local,
+                           final Type type) {
+        setLocalType( local,
+                      type );
+        storeInsn( type,
+                   local );
+    }
+
+    /**
+     * Generates the instruction to load an element from an array.
+     * 
+     * @param type the type of the array element to be loaded.
+     */
+    public void arrayLoad(final Type type) {
+        this.mv.visitInsn( type.getOpcode( Opcodes.IALOAD ) );
+    }
+
+    /**
+     * Generates the instruction to store an element in an array.
+     * 
+     * @param type the type of the array element to be stored.
+     */
+    public void arrayStore(final Type type) {
+        this.mv.visitInsn( type.getOpcode( Opcodes.IASTORE ) );
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to manage the stack
+    // ------------------------------------------------------------------------
+
+    /**
+     * Generates a POP instruction.
+     */
+    public void pop() {
+        this.mv.visitInsn( Opcodes.POP );
+    }
+
+    /**
+     * Generates a POP2 instruction.
+     */
+    public void pop2() {
+        this.mv.visitInsn( Opcodes.POP2 );
+    }
+
+    /**
+     * Generates a DUP instruction.
+     */
+    public void dup() {
+        this.mv.visitInsn( Opcodes.DUP );
+    }
+
+    /**
+     * Generates a DUP2 instruction.
+     */
+    public void dup2() {
+        this.mv.visitInsn( Opcodes.DUP2 );
+    }
+
+    /**
+     * Generates a DUP_X1 instruction.
+     */
+    public void dupX1() {
+        this.mv.visitInsn( Opcodes.DUP_X1 );
+    }
+
+    /**
+     * Generates a DUP_X2 instruction.
+     */
+    public void dupX2() {
+        this.mv.visitInsn( Opcodes.DUP_X2 );
+    }
+
+    /**
+     * Generates a DUP2_X1 instruction.
+     */
+    public void dup2X1() {
+        this.mv.visitInsn( Opcodes.DUP2_X1 );
+    }
+
+    /**
+     * Generates a DUP2_X2 instruction.
+     */
+    public void dup2X2() {
+        this.mv.visitInsn( Opcodes.DUP2_X2 );
+    }
+
+    /**
+     * Generates a SWAP instruction.
+     */
+    public void swap() {
+        this.mv.visitInsn( Opcodes.SWAP );
+    }
+
+    /**
+     * Generates the instructions to swap the top two stack values.
+     * 
+     * @param prev type of the top - 1 stack value.
+     * @param type type of the top stack value.
+     */
+    public void swap(final Type prev,
+                     final Type type) {
+        if ( type.getSize() == 1 ) {
+            if ( prev.getSize() == 1 ) {
+                swap(); // same as dupX1(), pop();
+            } else {
+                dupX2();
+                pop();
+            }
+        } else {
+            if ( prev.getSize() == 1 ) {
+                dup2X1();
+                pop2();
+            } else {
+                dup2X2();
+                pop2();
+            }
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to do mathematical and logical operations
+    // ------------------------------------------------------------------------
+
+    /**
+     * Generates the instruction to do the specified mathematical or logical
+     * operation.
+     * 
+     * @param op a mathematical or logical operation. Must be one of ADD, SUB,
+     *        MUL, DIV, REM, NEG, SHL, SHR, USHR, AND, OR, XOR.
+     * @param type the type of the operand(s) for this operation.
+     */
+    public void math(final int op,
+                     final Type type) {
+        this.mv.visitInsn( type.getOpcode( op ) );
+    }
+
+    /**
+     * Generates the instructions to compute the bitwise negation of the top
+     * stack value.
+     */
+    public void not() {
+        this.mv.visitInsn( Opcodes.ICONST_1 );
+        this.mv.visitInsn( Opcodes.IXOR );
+    }
+
+    /**
+     * Generates the instruction to increment the given local variable.
+     * 
+     * @param local the local variable to be incremented.
+     * @param amount the amount by which the local variable must be incremented.
+     */
+    public void iinc(final int local,
+                     final int amount) {
+        this.mv.visitIincInsn( local,
+                               amount );
+    }
+
+    /**
+     * Generates the instructions to cast a numerical value from one type to
+     * another.
+     * 
+     * @param from the type of the top stack value
+     * @param to the type into which this value must be cast.
+     */
+    public void cast(final Type from,
+                     final Type to) {
+        if ( from != to ) {
+            if ( from == Type.DOUBLE_TYPE ) {
+                if ( to == Type.FLOAT_TYPE ) {
+                    this.mv.visitInsn( Opcodes.D2F );
+                } else if ( to == Type.LONG_TYPE ) {
+                    this.mv.visitInsn( Opcodes.D2L );
+                } else {
+                    this.mv.visitInsn( Opcodes.D2I );
+                    cast( Type.INT_TYPE,
+                          to );
+                }
+            } else if ( from == Type.FLOAT_TYPE ) {
+                if ( to == Type.DOUBLE_TYPE ) {
+                    this.mv.visitInsn( Opcodes.F2D );
+                } else if ( to == Type.LONG_TYPE ) {
+                    this.mv.visitInsn( Opcodes.F2L );
+                } else {
+                    this.mv.visitInsn( Opcodes.F2I );
+                    cast( Type.INT_TYPE,
+                          to );
+                }
+            } else if ( from == Type.LONG_TYPE ) {
+                if ( to == Type.DOUBLE_TYPE ) {
+                    this.mv.visitInsn( Opcodes.L2D );
+                } else if ( to == Type.FLOAT_TYPE ) {
+                    this.mv.visitInsn( Opcodes.L2F );
+                } else {
+                    this.mv.visitInsn( Opcodes.L2I );
+                    cast( Type.INT_TYPE,
+                          to );
+                }
+            } else {
+                if ( to == Type.BYTE_TYPE ) {
+                    this.mv.visitInsn( Opcodes.I2B );
+                } else if ( to == Type.CHAR_TYPE ) {
+                    this.mv.visitInsn( Opcodes.I2C );
+                } else if ( to == Type.DOUBLE_TYPE ) {
+                    this.mv.visitInsn( Opcodes.I2D );
+                } else if ( to == Type.FLOAT_TYPE ) {
+                    this.mv.visitInsn( Opcodes.I2F );
+                } else if ( to == Type.LONG_TYPE ) {
+                    this.mv.visitInsn( Opcodes.I2L );
+                } else if ( to == Type.SHORT_TYPE ) {
+                    this.mv.visitInsn( Opcodes.I2S );
+                }
+            }
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to do boxing and unboxing operations
+    // ------------------------------------------------------------------------
+
+    /**
+     * Generates the instructions to box the top stack value. This value is
+     * replaced by its boxed equivalent on top of the stack.
+     * 
+     * @param type the type of the top stack value.
+     */
+    public void box(final Type type) {
+        if ( type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY ) {
+            return;
+        }
+        if ( type == Type.VOID_TYPE ) {
+            push( (String) null );
+        } else {
+            Type boxed = type;
+            switch ( type.getSort() ) {
+                case Type.BYTE :
+                    boxed = GeneratorAdapter.BYTE_TYPE;
+                    break;
+                case Type.BOOLEAN :
+                    boxed = GeneratorAdapter.BOOLEAN_TYPE;
+                    break;
+                case Type.SHORT :
+                    boxed = GeneratorAdapter.SHORT_TYPE;
+                    break;
+                case Type.CHAR :
+                    boxed = GeneratorAdapter.CHARACTER_TYPE;
+                    break;
+                case Type.INT :
+                    boxed = GeneratorAdapter.INTEGER_TYPE;
+                    break;
+                case Type.FLOAT :
+                    boxed = GeneratorAdapter.FLOAT_TYPE;
+                    break;
+                case Type.LONG :
+                    boxed = GeneratorAdapter.LONG_TYPE;
+                    break;
+                case Type.DOUBLE :
+                    boxed = GeneratorAdapter.DOUBLE_TYPE;
+                    break;
+            }
+            newInstance( boxed );
+            if ( type.getSize() == 2 ) {
+                // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o
+                dupX2();
+                dupX2();
+                pop();
+            } else {
+                // p -> po -> opo -> oop -> o
+                dupX1();
+                swap();
+            }
+            invokeConstructor( boxed,
+                               new Method( "<init>",
+                                           Type.VOID_TYPE,
+                                           new Type[]{type} ) );
+        }
+    }
+
+    /**
+     * Generates the instructions to unbox the top stack value. This value is
+     * replaced by its unboxed equivalent on top of the stack.
+     * 
+     * @param type the type of the top stack value.
+     */
+    public void unbox(final Type type) {
+        Type t = GeneratorAdapter.NUMBER_TYPE;
+        Method sig = null;
+        switch ( type.getSort() ) {
+            case Type.VOID :
+                return;
+            case Type.CHAR :
+                t = GeneratorAdapter.CHARACTER_TYPE;
+                sig = GeneratorAdapter.CHAR_VALUE;
+                break;
+            case Type.BOOLEAN :
+                t = GeneratorAdapter.BOOLEAN_TYPE;
+                sig = GeneratorAdapter.BOOLEAN_VALUE;
+                break;
+            case Type.DOUBLE :
+                sig = GeneratorAdapter.DOUBLE_VALUE;
+                break;
+            case Type.FLOAT :
+                sig = GeneratorAdapter.FLOAT_VALUE;
+                break;
+            case Type.LONG :
+                sig = GeneratorAdapter.LONG_VALUE;
+                break;
+            case Type.INT :
+            case Type.SHORT :
+            case Type.BYTE :
+                sig = GeneratorAdapter.INT_VALUE;
+        }
+        if ( sig == null ) {
+            checkCast( type );
+        } else {
+            checkCast( t );
+            invokeVirtual( t,
+                           sig );
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to jump to other instructions
+    // ------------------------------------------------------------------------
+
+    /**
+     * Creates a new {@link Label}.
+     * 
+     * @return a new {@link Label}.
+     */
+    public Label newLabel() {
+        return new Label();
+    }
+
+    /**
+     * Marks the current code position with the given label.
+     * 
+     * @param label a label.
+     */
+    public void mark(final Label label) {
+        this.mv.visitLabel( label );
+    }
+
+    /**
+     * Marks the current code position with a new label.
+     * 
+     * @return the label that was created to mark the current code position.
+     */
+    public Label mark() {
+        final Label label = new Label();
+        this.mv.visitLabel( label );
+        return label;
+    }
+
+    /**
+     * Generates the instructions to jump to a label based on the comparison of
+     * the top two stack values.
+     * 
+     * @param type the type of the top two stack values.
+     * @param mode how these values must be compared. One of EQ, NE, LT, GE, GT,
+     *        LE.
+     * @param label where to jump if the comparison result is <tt>true</tt>.
+     */
+    public void ifCmp(final Type type,
+                      final int mode,
+                      final Label label) {
+        int intOp = -1;
+        int jumpMode = mode;
+        switch ( mode ) {
+            case GE :
+                jumpMode = GeneratorAdapter.LT;
+                break;
+            case LE :
+                jumpMode = GeneratorAdapter.GT;
+                break;
+        }
+        switch ( type.getSort() ) {
+            case Type.LONG :
+                this.mv.visitInsn( Opcodes.LCMP );
+                break;
+            case Type.DOUBLE :
+                this.mv.visitInsn( Opcodes.DCMPG );
+                break;
+            case Type.FLOAT :
+                this.mv.visitInsn( Opcodes.FCMPG );
+                break;
+            case Type.ARRAY :
+            case Type.OBJECT :
+                switch ( mode ) {
+                    case EQ :
+                        this.mv.visitJumpInsn( Opcodes.IF_ACMPEQ,
+                                               label );
+                        return;
+                    case NE :
+                        this.mv.visitJumpInsn( Opcodes.IF_ACMPNE,
+                                               label );
+                        return;
+                }
+                throw new IllegalArgumentException( "Bad comparison for type " + type );
+            default :
+                switch ( mode ) {
+                    case EQ :
+                        intOp = Opcodes.IF_ICMPEQ;
+                        break;
+                    case NE :
+                        intOp = Opcodes.IF_ICMPNE;
+                        break;
+                    case GE :
+                        intOp = Opcodes.IF_ICMPGE;
+                        break;
+                    case LT :
+                        intOp = Opcodes.IF_ICMPLT;
+                        break;
+                    case LE :
+                        intOp = Opcodes.IF_ICMPLE;
+                        break;
+                    case GT :
+                        intOp = Opcodes.IF_ICMPGT;
+                        break;
+                }
+                this.mv.visitJumpInsn( intOp,
+                                       label );
+                return;
+        }
+        this.mv.visitJumpInsn( jumpMode,
+                               label );
+    }
+
+    /**
+     * Generates the instructions to jump to a label based on the comparison of
+     * the top two integer stack values.
+     * 
+     * @param mode how these values must be compared. One of EQ, NE, LT, GE, GT,
+     *        LE.
+     * @param label where to jump if the comparison result is <tt>true</tt>.
+     */
+    public void ifICmp(final int mode,
+                       final Label label) {
+        ifCmp( Type.INT_TYPE,
+               mode,
+               label );
+    }
+
+    /**
+     * Generates the instructions to jump to a label based on the comparison of
+     * the top integer stack value with zero.
+     * 
+     * @param mode how these values must be compared. One of EQ, NE, LT, GE, GT,
+     *        LE.
+     * @param label where to jump if the comparison result is <tt>true</tt>.
+     */
+    public void ifZCmp(final int mode,
+                       final Label label) {
+        this.mv.visitJumpInsn( mode,
+                               label );
+    }
+
+    /**
+     * Generates the instruction to jump to the given label if the top stack
+     * value is null.
+     * 
+     * @param label where to jump if the condition is <tt>true</tt>.
+     */
+    public void ifNull(final Label label) {
+        this.mv.visitJumpInsn( Opcodes.IFNULL,
+                               label );
+    }
+
+    /**
+     * Generates the instruction to jump to the given label if the top stack
+     * value is not null.
+     * 
+     * @param label where to jump if the condition is <tt>true</tt>.
+     */
+    public void ifNonNull(final Label label) {
+        this.mv.visitJumpInsn( Opcodes.IFNONNULL,
+                               label );
+    }
+
+    /**
+     * Generates the instruction to jump to the given label.
+     * 
+     * @param label where to jump if the condition is <tt>true</tt>.
+     */
+    public void goTo(final Label label) {
+        this.mv.visitJumpInsn( Opcodes.GOTO,
+                               label );
+    }
+
+    /**
+     * Generates a RET instruction.
+     * 
+     * @param local a local variable identifier, as returned by {@link #newLocal
+     *        newLocal}.
+     */
+    public void ret(final int local) {
+        this.mv.visitVarInsn( Opcodes.RET,
+                              local );
+    }
+
+    /**
+     * Generates the instructions for a switch statement.
+     * 
+     * @param keys the switch case keys.
+     * @param generator a generator to generate the code for the switch cases.
+     */
+    public void tableSwitch(final int[] keys,
+                            final TableSwitchGenerator generator) {
+        float density;
+        if ( keys.length == 0 ) {
+            density = 0;
+        } else {
+            density = (float) keys.length / (keys[keys.length - 1] - keys[0] + 1);
+        }
+        tableSwitch( keys,
+                     generator,
+                     density >= 0.5f );
+    }
+
+    /**
+     * Generates the instructions for a switch statement.
+     * 
+     * @param keys the switch case keys.
+     * @param generator a generator to generate the code for the switch cases.
+     * @param useTable <tt>true</tt> to use a TABLESWITCH instruction, or
+     *        <tt>false</tt> to use a LOOKUPSWITCH instruction.
+     */
+    public void tableSwitch(final int[] keys,
+                            final TableSwitchGenerator generator,
+                            final boolean useTable) {
+        for ( int i = 1; i < keys.length; ++i ) {
+            if ( keys[i] < keys[i - 1] ) {
+                throw new IllegalArgumentException( "keys must be sorted ascending" );
+            }
+        }
+        final Label def = newLabel();
+        final Label end = newLabel();
+        if ( keys.length > 0 ) {
+            final int len = keys.length;
+            final int min = keys[0];
+            final int max = keys[len - 1];
+            final int range = max - min + 1;
+            if ( useTable ) {
+                final Label[] labels = new Label[range];
+                Arrays.fill( labels,
+                             def );
+                for ( int i = 0; i < len; ++i ) {
+                    labels[keys[i] - min] = newLabel();
+                }
+                this.mv.visitTableSwitchInsn( min,
+                                              max,
+                                              def,
+                                              labels );
+                for ( int i = 0; i < range; ++i ) {
+                    final Label label = labels[i];
+                    if ( label != def ) {
+                        mark( label );
+                        generator.generateCase( i + min,
+                                                end );
+                    }
+                }
+            } else {
+                final Label[] labels = new Label[len];
+                for ( int i = 0; i < len; ++i ) {
+                    labels[i] = newLabel();
+                }
+                this.mv.visitLookupSwitchInsn( def,
+                                               keys,
+                                               labels );
+                for ( int i = 0; i < len; ++i ) {
+                    mark( labels[i] );
+                    generator.generateCase( keys[i],
+                                            end );
+                }
+            }
+        }
+        mark( def );
+        generator.generateDefault();
+        mark( end );
+    }
+
+    /**
+     * Generates the instruction to return the top stack value to the caller.
+     */
+    public void returnValue() {
+        this.mv.visitInsn( this.returnType.getOpcode( Opcodes.IRETURN ) );
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to load and store fields
+    // ------------------------------------------------------------------------
+
+    /**
+     * Generates a get field or set field instruction.
+     * 
+     * @param opcode the instruction's opcode.
+     * @param ownerType the class in which the field is defined.
+     * @param name the name of the field.
+     * @param fieldType the type of the field.
+     */
+    private void fieldInsn(final int opcode,
+                           final Type ownerType,
+                           final String name,
+                           final Type fieldType) {
+        this.mv.visitFieldInsn( opcode,
+                                ownerType.getInternalName(),
+                                name,
+                                fieldType.getDescriptor() );
+    }
+
+    /**
+     * Generates the instruction to push the value of a static field on the
+     * stack.
+     * 
+     * @param owner the class in which the field is defined.
+     * @param name the name of the field.
+     * @param type the type of the field.
+     */
+    public void getStatic(final Type owner,
+                          final String name,
+                          final Type type) {
+        fieldInsn( Opcodes.GETSTATIC,
+                   owner,
+                   name,
+                   type );
+    }
+
+    /**
+     * Generates the instruction to store the top stack value in a static field.
+     * 
+     * @param owner the class in which the field is defined.
+     * @param name the name of the field.
+     * @param type the type of the field.
+     */
+    public void putStatic(final Type owner,
+                          final String name,
+                          final Type type) {
+        fieldInsn( Opcodes.PUTSTATIC,
+                   owner,
+                   name,
+                   type );
+    }
+
+    /**
+     * Generates the instruction to push the value of a non static field on the
+     * stack.
+     * 
+     * @param owner the class in which the field is defined.
+     * @param name the name of the field.
+     * @param type the type of the field.
+     */
+    public void getField(final Type owner,
+                         final String name,
+                         final Type type) {
+        fieldInsn( Opcodes.GETFIELD,
+                   owner,
+                   name,
+                   type );
+    }
+
+    /**
+     * Generates the instruction to store the top stack value in a non static
+     * field.
+     * 
+     * @param owner the class in which the field is defined.
+     * @param name the name of the field.
+     * @param type the type of the field.
+     */
+    public void putField(final Type owner,
+                         final String name,
+                         final Type type) {
+        fieldInsn( Opcodes.PUTFIELD,
+                   owner,
+                   name,
+                   type );
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to invoke methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Generates an invoke method instruction.
+     * 
+     * @param opcode the instruction's opcode.
+     * @param type the class in which the method is defined.
+     * @param method the method to be invoked.
+     */
+    private void invokeInsn(final int opcode,
+                            final Type type,
+                            final Method method) {
+        final String owner = type.getSort() == Type.ARRAY ? type.getDescriptor() : type.getInternalName();
+        this.mv.visitMethodInsn( opcode,
+                                 owner,
+                                 method.getName(),
+                                 method.getDescriptor() );
+    }
+
+    /**
+     * Generates the instruction to invoke a normal method.
+     * 
+     * @param owner the class in which the method is defined.
+     * @param method the method to be invoked.
+     */
+    public void invokeVirtual(final Type owner,
+                              final Method method) {
+        invokeInsn( Opcodes.INVOKEVIRTUAL,
+                    owner,
+                    method );
+    }
+
+    /**
+     * Generates the instruction to invoke a constructor.
+     * 
+     * @param type the class in which the constructor is defined.
+     * @param method the constructor to be invoked.
+     */
+    public void invokeConstructor(final Type type,
+                                  final Method method) {
+        invokeInsn( Opcodes.INVOKESPECIAL,
+                    type,
+                    method );
+    }
+
+    /**
+     * Generates the instruction to invoke a static method.
+     * 
+     * @param owner the class in which the method is defined.
+     * @param method the method to be invoked.
+     */
+    public void invokeStatic(final Type owner,
+                             final Method method) {
+        invokeInsn( Opcodes.INVOKESTATIC,
+                    owner,
+                    method );
+    }
+
+    /**
+     * Generates the instruction to invoke an interface method.
+     * 
+     * @param owner the class in which the method is defined.
+     * @param method the method to be invoked.
+     */
+    public void invokeInterface(final Type owner,
+                                final Method method) {
+        invokeInsn( Opcodes.INVOKEINTERFACE,
+                    owner,
+                    method );
+    }
+
+    // ------------------------------------------------------------------------
+    // Instructions to create objects and arrays
+    // ------------------------------------------------------------------------
+
+    /**
+     * Generates a type dependent instruction.
+     * 
+     * @param opcode the instruction's opcode.
+     * @param type the instruction's operand.
+     */
+    private void typeInsn(final int opcode,
+                          final Type type) {
+        String desc;
+        if ( type.getSort() == Type.ARRAY ) {
+            desc = type.getDescriptor();
+        } else {
+            desc = type.getInternalName();
+        }
+        this.mv.visitTypeInsn( opcode,
+                               desc );
+    }
+
+    /**
+     * Generates the instruction to create a new object.
+     * 
+     * @param type the class of the object to be created.
+     */
+    public void newInstance(final Type type) {
+        typeInsn( Opcodes.NEW,
+                  type );
+    }
+
+    /**
+     * Generates the instruction to create a new array.
+     * 
+     * @param type the type of the array elements.
+     */
+    public void newArray(final Type type) {
+        int typ;
+        switch ( type.getSort() ) {
+            case Type.BOOLEAN :
+                typ = Opcodes.T_BOOLEAN;
+                break;
+            case Type.CHAR :
+                typ = Opcodes.T_CHAR;
+                break;
+            case Type.BYTE :
+                typ = Opcodes.T_BYTE;
+                break;
+            case Type.SHORT :
+                typ = Opcodes.T_SHORT;
+                break;
+            case Type.INT :
+                typ = Opcodes.T_INT;
+                break;
+            case Type.FLOAT :
+                typ = Opcodes.T_FLOAT;
+                break;
+            case Type.LONG :
+                typ = Opcodes.T_LONG;
+                break;
+            case Type.DOUBLE :
+                typ = Opcodes.T_DOUBLE;
+                break;
+            default :
+                typeInsn( Opcodes.ANEWARRAY,
+                          type );
+                return;
+        }
+        this.mv.visitIntInsn( Opcodes.NEWARRAY,
+                              typ );
+    }
+
+    // ------------------------------------------------------------------------
+    // Miscelaneous instructions
+    // ------------------------------------------------------------------------
+
+    /**
+     * Generates the instruction to compute the length of an array.
+     */
+    public void arrayLength() {
+        this.mv.visitInsn( Opcodes.ARRAYLENGTH );
+    }
+
+    /**
+     * Generates the instruction to throw an exception.
+     */
+    public void throwException() {
+        this.mv.visitInsn( Opcodes.ATHROW );
+    }
+
+    /**
+     * Generates the instructions to create and throw an exception. The
+     * exception class must have a constructor with a single String argument.
+     * 
+     * @param type the class of the exception to be thrown.
+     * @param msg the detailed message of the exception.
+     */
+    public void throwException(final Type type,
+                               final String msg) {
+        newInstance( type );
+        dup();
+        push( msg );
+        invokeConstructor( type,
+                           Method.getMethod( "void <init> (String)" ) );
+        throwException();
+    }
+
+    /**
+     * Generates the instruction to check that the top stack value is of the
+     * given type.
+     * 
+     * @param type a class or interface type.
+     */
+    public void checkCast(final Type type) {
+        if ( !type.equals( GeneratorAdapter.OBJECT_TYPE ) ) {
+            typeInsn( Opcodes.CHECKCAST,
+                      type );
+        }
+    }
+
+    /**
+     * Generates the instruction to test if the top stack value is of the given
+     * type.
+     * 
+     * @param type a class or interface type.
+     */
+    public void instanceOf(final Type type) {
+        typeInsn( Opcodes.INSTANCEOF,
+                  type );
+    }
+
+    /**
+     * Generates the instruction to get the monitor of the top stack value.
+     */
+    public void monitorEnter() {
+        this.mv.visitInsn( Opcodes.MONITORENTER );
+    }
+
+    /**
+     * Generates the instruction to release the monitor of the top stack value.
+     */
+    public void monitorExit() {
+        this.mv.visitInsn( Opcodes.MONITOREXIT );
+    }
+
+    // ------------------------------------------------------------------------
+    // Non instructions
+    // ------------------------------------------------------------------------
+
+    /**
+     * Marks the end of the visited method.
+     */
+    public void endMethod() {
+        if ( (this.access & Opcodes.ACC_ABSTRACT) == 0 ) {
+            this.mv.visitMaxs( 0,
+                               0 );
+        }
+    }
+
+    /**
+     * Marks the start of an exception handler.
+     * 
+     * @param start beginning of the exception handler's scope (inclusive).
+     * @param end end of the exception handler's scope (exclusive).
+     * @param exception internal name of the type of exceptions handled by the
+     *        handler.
+     */
+    public void catchException(final Label start,
+                               final Label end,
+                               final Type exception) {
+        this.mv.visitTryCatchBlock( start,
+                                    end,
+                                    mark(),
+                                    exception.getInternalName() );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/LocalVariablesSorter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/LocalVariablesSorter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/LocalVariablesSorter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,152 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.commons;
+
+import org.drools.asm.Label;
+import org.drools.asm.MethodAdapter;
+import org.drools.asm.MethodVisitor;
+import org.drools.asm.Opcodes;
+import org.drools.asm.Type;
+
+/**
+ * A {@link MethodAdapter} that renumbers local variables in their order of
+ * appearance. This adapter allows one to easily add new local variables to a
+ * method.
+ * 
+ * @author Chris Nokleberg
+ * @author Eric Bruneton
+ */
+public class LocalVariablesSorter extends MethodAdapter {
+
+    /**
+     * Mapping from old to new local variable indexes. A local variable at index
+     * i of size 1 is remapped to 'mapping[2*i]', while a local variable at
+     * index i of size 2 is remapped to 'mapping[2*i+1]'.
+     */
+    private int[]       mapping = new int[40];
+
+    protected final int firstLocal;
+
+    private int         nextLocal;
+
+    public LocalVariablesSorter(final int access,
+                                final String desc,
+                                final MethodVisitor mv) {
+        super( mv );
+        final Type[] args = Type.getArgumentTypes( desc );
+        this.nextLocal = ((Opcodes.ACC_STATIC & access) != 0) ? 0 : 1;
+        for ( int i = 0; i < args.length; i++ ) {
+            this.nextLocal += args[i].getSize();
+        }
+        this.firstLocal = this.nextLocal;
+    }
+
+    public void visitVarInsn(final int opcode,
+                             final int var) {
+        int size;
+        switch ( opcode ) {
+            case Opcodes.LLOAD :
+            case Opcodes.LSTORE :
+            case Opcodes.DLOAD :
+            case Opcodes.DSTORE :
+                size = 2;
+                break;
+            default :
+                size = 1;
+        }
+        this.mv.visitVarInsn( opcode,
+                              remap( var,
+                                     size ) );
+    }
+
+    public void visitIincInsn(final int var,
+                              final int increment) {
+        this.mv.visitIincInsn( remap( var,
+                                      1 ),
+                               increment );
+    }
+
+    public void visitMaxs(final int maxStack,
+                          final int maxLocals) {
+        this.mv.visitMaxs( maxStack,
+                           this.nextLocal );
+    }
+
+    public void visitLocalVariable(final String name,
+                                   final String desc,
+                                   final String signature,
+                                   final Label start,
+                                   final Label end,
+                                   final int index) {
+        final int size = "J".equals( desc ) || "D".equals( desc ) ? 2 : 1;
+        this.mv.visitLocalVariable( name,
+                                    desc,
+                                    signature,
+                                    start,
+                                    end,
+                                    remap( index,
+                                           size ) );
+    }
+
+    // -------------
+
+    protected int newLocal(final int size) {
+        final int var = this.nextLocal;
+        this.nextLocal += size;
+        return var;
+    }
+
+    private int remap(final int var,
+                      final int size) {
+        if ( var < this.firstLocal ) {
+            return var;
+        }
+        final int key = 2 * var + size - 1;
+        final int length = this.mapping.length;
+        if ( key >= length ) {
+            final int[] newMapping = new int[Math.max( 2 * length,
+                                                       key + 1 )];
+            System.arraycopy( this.mapping,
+                              0,
+                              newMapping,
+                              0,
+                              length );
+            this.mapping = newMapping;
+        }
+        int value = this.mapping[key];
+        if ( value == 0 ) {
+            value = this.nextLocal + 1;
+            this.mapping[key] = value;
+            this.nextLocal += size;
+        }
+        return value - 1;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/Method.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/Method.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/Method.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,239 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.commons;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.asm.Type;
+
+/**
+ * A named method descriptor.
+ * 
+ * @author Juozas Baliuka
+ * @author Chris Nokleberg
+ * @author Eric Bruneton
+ */
+public class Method {
+
+    /**
+     * The method name.
+     */
+    private final String     name;
+
+    /**
+     * The method descriptor.
+     */
+    private final String     desc;
+
+    /**
+     * Maps primitive Java type names to their descriptors.
+     */
+    private final static Map DESCRIPTORS;
+
+    static {
+        DESCRIPTORS = new HashMap();
+        Method.DESCRIPTORS.put( "void",
+                                "V" );
+        Method.DESCRIPTORS.put( "byte",
+                                "B" );
+        Method.DESCRIPTORS.put( "char",
+                                "C" );
+        Method.DESCRIPTORS.put( "double",
+                                "D" );
+        Method.DESCRIPTORS.put( "float",
+                                "F" );
+        Method.DESCRIPTORS.put( "int",
+                                "I" );
+        Method.DESCRIPTORS.put( "long",
+                                "J" );
+        Method.DESCRIPTORS.put( "short",
+                                "S" );
+        Method.DESCRIPTORS.put( "boolean",
+                                "Z" );
+    }
+
+    /**
+     * Creates a new {@link Method}.
+     * 
+     * @param name the method's name.
+     * @param desc the method's descriptor.
+     */
+    public Method(final String name,
+                  final String desc) {
+        this.name = name;
+        this.desc = desc;
+    }
+
+    /**
+     * Creates a new {@link Method}.
+     * 
+     * @param name the method's name.
+     * @param returnType the method's return type.
+     * @param argumentTypes the method's argument types.
+     */
+    public Method(final String name,
+                  final Type returnType,
+                  final Type[] argumentTypes) {
+        this( name,
+              Type.getMethodDescriptor( returnType,
+                                        argumentTypes ) );
+    }
+
+    /**
+     * Returns a {@link Method} corresponding to the given Java method
+     * declaration.
+     * 
+     * @param method a Java method declaration, without argument names, of the
+     *        form "returnType name (argumentType1, ... argumentTypeN)", where
+     *        the types are in plain Java (e.g. "int", "float",
+     *        "java.util.List", ...).
+     * @return a {@link Method} corresponding to the given Java method
+     *         declaration.
+     * @throws IllegalArgumentException if <code>method</code> could not get
+     *         parsed.
+     */
+    public static Method getMethod(final String method) throws IllegalArgumentException {
+        final int space = method.indexOf( ' ' );
+        int start = method.indexOf( '(',
+                                    space ) + 1;
+        final int end = method.indexOf( ')',
+                                        start );
+        if ( space == -1 || start == -1 || end == -1 ) {
+            throw new IllegalArgumentException();
+        }
+        // TODO: Check validity of returnType, methodName and arguments.
+        final String returnType = method.substring( 0,
+                                                    space );
+        final String methodName = method.substring( space + 1,
+                                                    start - 1 ).trim();
+        final StringBuffer sb = new StringBuffer();
+        sb.append( '(' );
+        int p;
+        do {
+            p = method.indexOf( ',',
+                                start );
+            if ( p == -1 ) {
+                sb.append( map( method.substring( start,
+                                                  end ).trim() ) );
+            } else {
+                sb.append( map( method.substring( start,
+                                                  p ).trim() ) );
+                start = p + 1;
+            }
+        } while ( p != -1 );
+        sb.append( ')' );
+        sb.append( map( returnType ) );
+        return new Method( methodName,
+                           sb.toString() );
+    }
+
+    private static String map(final String type) {
+        if ( type.equals( "" ) ) {
+            return type;
+        }
+
+        final StringBuffer sb = new StringBuffer();
+        int index = 0;
+        while ( (index = type.indexOf( "[]",
+                                       index ) + 1) > 0 ) {
+            sb.append( '[' );
+        }
+
+        final String t = type.substring( 0,
+                                         type.length() - sb.length() * 2 );
+        final String desc = (String) Method.DESCRIPTORS.get( t );
+        if ( desc != null ) {
+            sb.append( desc );
+        } else {
+            sb.append( 'L' );
+            if ( t.indexOf( '.' ) < 0 ) {
+                sb.append( "java/lang/" + t );
+            } else {
+                sb.append( t.replace( '.',
+                                      '/' ) );
+            }
+            sb.append( ';' );
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Returns the name of the method described by this object.
+     * 
+     * @return the name of the method described by this object.
+     */
+    public String getName() {
+        return this.name;
+    }
+
+    /**
+     * Returns the descriptor of the method described by this object.
+     * 
+     * @return the descriptor of the method described by this object.
+     */
+    public String getDescriptor() {
+        return this.desc;
+    }
+
+    /**
+     * Returns the return type of the method described by this object.
+     * 
+     * @return the return type of the method described by this object.
+     */
+    public Type getReturnType() {
+        return Type.getReturnType( this.desc );
+    }
+
+    /**
+     * Returns the argument types of the method described by this object.
+     * 
+     * @return the argument types of the method described by this object.
+     */
+    public Type[] getArgumentTypes() {
+        return Type.getArgumentTypes( this.desc );
+    }
+
+    public String toString() {
+        return this.name + this.desc;
+    }
+
+    public boolean equals(final Object o) {
+        if ( !(o instanceof Method) ) {
+            return false;
+        }
+        final Method other = (Method) o;
+        return this.name.equals( other.name ) && this.desc.equals( other.desc );
+    }
+
+    public int hashCode() {
+        return this.name.hashCode() ^ this.desc.hashCode();
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/SerialVersionUIDAdder.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/SerialVersionUIDAdder.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/SerialVersionUIDAdder.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,492 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.commons;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.drools.asm.ClassAdapter;
+import org.drools.asm.ClassVisitor;
+import org.drools.asm.FieldVisitor;
+import org.drools.asm.MethodVisitor;
+import org.drools.asm.Opcodes;
+
+/**
+ * A {@link ClassAdapter} that adds a serial version unique identifier to a
+ * class if missing. Here is typical usage of this class:
+ * 
+ * <pre>
+ *   ClassWriter cw = new ClassWriter(...);
+ *   ClassVisitor sv = new SerialVersionUIDAdder(cw);
+ *   ClassVisitor ca = new MyClassAdapter(sv);
+ *   new ClassReader(orginalClass).accept(ca, false);
+ * </pre>
+ * 
+ * The SVUID algorithm can be found <a href=
+ * "http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html"
+ * >http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html</a>:
+ * 
+ * <pre>
+ * The serialVersionUID is computed using the signature of a stream of bytes
+ * that reflect the class definition. The National Institute of Standards and
+ * Technology (NIST) Secure Hash Algorithm (SHA-1) is used to compute a
+ * signature for the stream. The first two 32-bit quantities are used to form a
+ * 64-bit hash. A java.lang.DataOutputStream is used to convert primitive data
+ * types to a sequence of bytes. The values input to the stream are defined by
+ * the Java Virtual Machine (VM) specification for classes.
+ *
+ * The sequence of items in the stream is as follows:
+ *
+ * 1. The class name written using UTF encoding.
+ * 2. The class modifiers written as a 32-bit integer.
+ * 3. The name of each interface sorted by name written using UTF encoding.
+ * 4. For each field of the class sorted by field name (except private static
+ * and private transient fields):
+ * 1. The name of the field in UTF encoding.
+ * 2. The modifiers of the field written as a 32-bit integer.
+ * 3. The descriptor of the field in UTF encoding
+ * 5. If a class initializer exists, write out the following:
+ * 1. The name of the method, &lt;clinit&gt;, in UTF encoding.
+ * 2. The modifier of the method, java.lang.reflect.Modifier.STATIC,
+ * written as a 32-bit integer.
+ * 3. The descriptor of the method, ()V, in UTF encoding.
+ * 6. For each non-private constructor sorted by method name and signature:
+ * 1. The name of the method, &lt;init&gt;, in UTF encoding.
+ * 2. The modifiers of the method written as a 32-bit integer.
+ * 3. The descriptor of the method in UTF encoding.
+ * 7. For each non-private method sorted by method name and signature:
+ * 1. The name of the method in UTF encoding.
+ * 2. The modifiers of the method written as a 32-bit integer.
+ * 3. The descriptor of the method in UTF encoding.
+ * 8. The SHA-1 algorithm is executed on the stream of bytes produced by
+ * DataOutputStream and produces five 32-bit values sha[0..4].
+ *
+ * 9. The hash value is assembled from the first and second 32-bit values of 
+ * the SHA-1 message digest. If the result of the message digest, the five
+ * 32-bit words H0 H1 H2 H3 H4, is in an array of five int values named 
+ * sha, the hash value would be computed as follows:
+ *
+ * long hash = ((sha[0] &gt;&gt;&gt; 24) &amp; 0xFF) |
+ * ((sha[0] &gt;&gt;&gt; 16) &amp; 0xFF) &lt;&lt; 8 |
+ * ((sha[0] &gt;&gt;&gt; 8) &amp; 0xFF) &lt;&lt; 16 |
+ * ((sha[0] &gt;&gt;&gt; 0) &amp; 0xFF) &lt;&lt; 24 |
+ * ((sha[1] &gt;&gt;&gt; 24) &amp; 0xFF) &lt;&lt; 32 |
+ * ((sha[1] &gt;&gt;&gt; 16) &amp; 0xFF) &lt;&lt; 40 |
+ * ((sha[1] &gt;&gt;&gt; 8) &amp; 0xFF) &lt;&lt; 48 |
+ * ((sha[1] &gt;&gt;&gt; 0) &amp; 0xFF) &lt;&lt; 56;
+ * </pre>
+ * 
+ * @author Rajendra Inamdar, Vishal Vishnoi
+ */
+public class SerialVersionUIDAdder extends ClassAdapter {
+
+    /**
+     * Flag that indicates if we need to compute SVUID.
+     */
+    protected boolean    computeSVUID;
+
+    /**
+     * Set to true if the class already has SVUID.
+     */
+    protected boolean    hasSVUID;
+
+    /**
+     * Classes access flags.
+     */
+    protected int        access;
+
+    /**
+     * Internal name of the class
+     */
+    protected String     name;
+
+    /**
+     * Interfaces implemented by the class.
+     */
+    protected String[]   interfaces;
+
+    /**
+     * Collection of fields. (except private static and private transient
+     * fields)
+     */
+    protected Collection svuidFields;
+
+    /**
+     * Set to true if the class has static initializer.
+     */
+    protected boolean    hasStaticInitializer;
+
+    /**
+     * Collection of non-private constructors.
+     */
+    protected Collection svuidConstructors;
+
+    /**
+     * Collection of non-private methods.
+     */
+    protected Collection svuidMethods;
+
+    /**
+     * Creates a new {@link SerialVersionUIDAdder}.
+     * 
+     * @param cv a {@link ClassVisitor} to which this visitor will delegate
+     *        calls.
+     */
+    public SerialVersionUIDAdder(final ClassVisitor cv) {
+        super( cv );
+        this.svuidFields = new ArrayList();
+        this.svuidConstructors = new ArrayList();
+        this.svuidMethods = new ArrayList();
+    }
+
+    // ------------------------------------------------------------------------
+    // Overriden methods
+    // ------------------------------------------------------------------------
+
+    /*
+     * Visit class header and get class name, access , and intefraces
+     * informatoin (step 1,2, and 3) for SVUID computation.
+     */
+    public void visit(final int version,
+                      final int access,
+                      final String name,
+                      final String signature,
+                      final String superName,
+                      final String[] interfaces) {
+        this.computeSVUID = (access & Opcodes.ACC_INTERFACE) == 0;
+
+        if ( this.computeSVUID ) {
+            this.name = name;
+            this.access = access;
+            this.interfaces = interfaces;
+        }
+
+        super.visit( version,
+                     access,
+                     name,
+                     signature,
+                     superName,
+                     interfaces );
+    }
+
+    /*
+     * Visit the methods and get constructor and method information (step 5 and
+     * 7). Also determince if there is a class initializer (step 6).
+     */
+    public MethodVisitor visitMethod(final int access,
+                                     final String name,
+                                     final String desc,
+                                     final String signature,
+                                     final String[] exceptions) {
+        if ( this.computeSVUID ) {
+            if ( name.equals( "<clinit>" ) ) {
+                this.hasStaticInitializer = true;
+            }
+            /*
+             * Remembers non private constructors and methods for SVUID
+             * computation For constructor and method modifiers, only the
+             * ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
+             * ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT and ACC_STRICT flags
+             * are used.
+             */
+            final int mods = access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_SYNCHRONIZED | Opcodes.ACC_NATIVE | Opcodes.ACC_ABSTRACT | Opcodes.ACC_STRICT);
+
+            // all non private methods
+            if ( (access & Opcodes.ACC_PRIVATE) == 0 ) {
+                if ( name.equals( "<init>" ) ) {
+                    this.svuidConstructors.add( new Item( name,
+                                                          mods,
+                                                          desc ) );
+                } else if ( !name.equals( "<clinit>" ) ) {
+                    this.svuidMethods.add( new Item( name,
+                                                     mods,
+                                                     desc ) );
+                }
+            }
+        }
+
+        return this.cv.visitMethod( access,
+                                    name,
+                                    desc,
+                                    signature,
+                                    exceptions );
+    }
+
+    /*
+     * Gets class field information for step 4 of the alogrithm. Also determines
+     * if the class already has a SVUID.
+     */
+    public FieldVisitor visitField(final int access,
+                                   final String name,
+                                   final String desc,
+                                   final String signature,
+                                   final Object value) {
+        if ( this.computeSVUID ) {
+            if ( name.equals( "serialVersionUID" ) ) {
+                // since the class already has SVUID, we won't be computing it.
+                this.computeSVUID = false;
+                this.hasSVUID = true;
+            }
+            /*
+             * Remember field for SVUID computation For field modifiers, only
+             * the ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC,
+             * ACC_FINAL, ACC_VOLATILE, and ACC_TRANSIENT flags are used when
+             * computing serialVersionUID values.
+             */
+            final int mods = access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_VOLATILE | Opcodes.ACC_TRANSIENT);
+
+            if ( ((access & Opcodes.ACC_PRIVATE) == 0) || ((access & (Opcodes.ACC_STATIC | Opcodes.ACC_TRANSIENT)) == 0) ) {
+                this.svuidFields.add( new Item( name,
+                                                mods,
+                                                desc ) );
+            }
+        }
+
+        return super.visitField( access,
+                                 name,
+                                 desc,
+                                 signature,
+                                 value );
+    }
+
+    /*
+     * Add the SVUID if class doesn't have one
+     */
+    public void visitEnd() {
+        // compute SVUID and add it to the class
+        if ( this.computeSVUID && !this.hasSVUID ) {
+            try {
+                this.cv.visitField( Opcodes.ACC_FINAL + Opcodes.ACC_STATIC,
+                                    "serialVersionUID",
+                                    "J",
+                                    null,
+                                    new Long( computeSVUID() ) );
+            } catch ( final Throwable e ) {
+                throw new RuntimeException( "Error while computing SVUID for " + this.name,
+                                            e );
+            }
+        }
+
+        super.visitEnd();
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Returns the value of SVUID if the class doesn't have one already. Please
+     * note that 0 is returned if the class already has SVUID, thus use
+     * <code>isHasSVUID</code> to determine if the class already had an SVUID.
+     * 
+     * @return Returns the serial version UID
+     * @throws IOException
+     * @throws NoSuchAlgorithmException
+     */
+    protected long computeSVUID() throws IOException,
+                                 NoSuchAlgorithmException {
+        if ( this.hasSVUID ) {
+            return 0;
+        }
+
+        ByteArrayOutputStream bos = null;
+        DataOutputStream dos = null;
+        long svuid = 0;
+
+        try {
+            bos = new ByteArrayOutputStream();
+            dos = new DataOutputStream( bos );
+
+            /*
+             * 1. The class name written using UTF encoding.
+             */
+            dos.writeUTF( this.name.replace( '/',
+                                             '.' ) );
+
+            /*
+             * 2. The class modifiers written as a 32-bit integer.
+             */
+            dos.writeInt( this.access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT) );
+
+            /*
+             * 3. The name of each interface sorted by name written using UTF
+             * encoding.
+             */
+            Arrays.sort( this.interfaces );
+            for ( int i = 0; i < this.interfaces.length; i++ ) {
+                dos.writeUTF( this.interfaces[i].replace( '/',
+                                                          '.' ) );
+            }
+
+            /*
+             * 4. For each field of the class sorted by field name (except
+             * private static and private transient fields):
+             * 
+             * 1. The name of the field in UTF encoding. 2. The modifiers of the
+             * field written as a 32-bit integer. 3. The descriptor of the field
+             * in UTF encoding
+             * 
+             * Note that field signatutes are not dot separated. Method and
+             * constructor signatures are dot separated. Go figure...
+             */
+            writeItems( this.svuidFields,
+                        dos,
+                        false );
+
+            /*
+             * 5. If a class initializer exists, write out the following: 1. The
+             * name of the method, <clinit>, in UTF encoding. 2. The modifier of
+             * the method, java.lang.reflect.Modifier.STATIC, written as a
+             * 32-bit integer. 3. The descriptor of the method, ()V, in UTF
+             * encoding.
+             */
+            if ( this.hasStaticInitializer ) {
+                dos.writeUTF( "<clinit>" );
+                dos.writeInt( Opcodes.ACC_STATIC );
+                dos.writeUTF( "()V" );
+            } // if..
+
+            /*
+             * 6. For each non-private constructor sorted by method name and
+             * signature: 1. The name of the method, <init>, in UTF encoding. 2.
+             * The modifiers of the method written as a 32-bit integer. 3. The
+             * descriptor of the method in UTF encoding.
+             */
+            writeItems( this.svuidConstructors,
+                        dos,
+                        true );
+
+            /*
+             * 7. For each non-private method sorted by method name and
+             * signature: 1. The name of the method in UTF encoding. 2. The
+             * modifiers of the method written as a 32-bit integer. 3. The
+             * descriptor of the method in UTF encoding.
+             */
+            writeItems( this.svuidMethods,
+                        dos,
+                        true );
+
+            dos.flush();
+
+            /*
+             * 8. The SHA-1 algorithm is executed on the stream of bytes
+             * produced by DataOutputStream and produces five 32-bit values
+             * sha[0..4].
+             */
+            final MessageDigest md = MessageDigest.getInstance( "SHA" );
+
+            /*
+             * 9. The hash value is assembled from the first and second 32-bit
+             * values of the SHA-1 message digest. If the result of the message
+             * digest, the five 32-bit words H0 H1 H2 H3 H4, is in an array of
+             * five int values named sha, the hash value would be computed as
+             * follows:
+             * 
+             * long hash = ((sha[0] >>> 24) & 0xFF) | ((sha[0] >>> 16) & 0xFF) <<
+             * 8 | ((sha[0] >>> 8) & 0xFF) << 16 | ((sha[0] >>> 0) & 0xFF) <<
+             * 24 | ((sha[1] >>> 24) & 0xFF) << 32 | ((sha[1] >>> 16) & 0xFF) <<
+             * 40 | ((sha[1] >>> 8) & 0xFF) << 48 | ((sha[1] >>> 0) & 0xFF) <<
+             * 56;
+             */
+            final byte[] hashBytes = md.digest( bos.toByteArray() );
+            for ( int i = Math.min( hashBytes.length,
+                                    8 ) - 1; i >= 0; i-- ) {
+                svuid = (svuid << 8) | (hashBytes[i] & 0xFF);
+            }
+        } finally {
+            // close the stream (if open)
+            if ( dos != null ) {
+                dos.close();
+            }
+        }
+
+        return svuid;
+    }
+
+    /**
+     * Sorts the items in the collection and writes it to the data output stream
+     * 
+     * @param itemCollection collection of items
+     * @param dos a <code>DataOutputStream</code> value
+     * @param dotted a <code>boolean</code> value
+     * @exception IOException if an error occurs
+     */
+    private void writeItems(final Collection itemCollection,
+                            final DataOutputStream dos,
+                            final boolean dotted) throws IOException {
+        final int size = itemCollection.size();
+        final Item items[] = (Item[]) itemCollection.toArray( new Item[size] );
+        Arrays.sort( items );
+        for ( int i = 0; i < size; i++ ) {
+            dos.writeUTF( items[i].name );
+            dos.writeInt( items[i].access );
+            dos.writeUTF( dotted ? items[i].desc.replace( '/',
+                                                          '.' ) : items[i].desc );
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Inner classes
+    // ------------------------------------------------------------------------
+
+    static class Item
+        implements
+        Comparable {
+
+        String name;
+
+        int    access;
+
+        String desc;
+
+        Item(final String name,
+             final int access,
+             final String desc) {
+            this.name = name;
+            this.access = access;
+            this.desc = desc;
+        }
+
+        public int compareTo(final Object o) {
+            final Item other = (Item) o;
+            int retVal = this.name.compareTo( other.name );
+            if ( retVal == 0 ) {
+                retVal = this.desc.compareTo( other.desc );
+            }
+            return retVal;
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/StaticInitMerger.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/StaticInitMerger.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/StaticInitMerger.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,117 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.commons;
+
+import org.drools.asm.ClassAdapter;
+import org.drools.asm.ClassVisitor;
+import org.drools.asm.MethodVisitor;
+import org.drools.asm.Opcodes;
+
+/**
+ * A {@link ClassAdapter} that merges clinit methods into a single one.
+ * 
+ * @author Eric Bruneton
+ */
+public class StaticInitMerger extends ClassAdapter {
+
+    private String        name;
+
+    private MethodVisitor clinit;
+
+    private String        prefix;
+
+    private int           counter;
+
+    public StaticInitMerger(final String prefix,
+                            final ClassVisitor cv) {
+        super( cv );
+        this.prefix = prefix;
+    }
+
+    public void visit(final int version,
+                      final int access,
+                      final String name,
+                      final String signature,
+                      final String superName,
+                      final String[] interfaces) {
+        this.cv.visit( version,
+                       access,
+                       name,
+                       signature,
+                       superName,
+                       interfaces );
+        this.name = name;
+    }
+
+    public MethodVisitor visitMethod(final int access,
+                                     final String name,
+                                     final String desc,
+                                     final String signature,
+                                     final String[] exceptions) {
+        MethodVisitor mv;
+        if ( name.equals( "<clinit>" ) ) {
+            final int a = Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC;
+            final String n = this.prefix + this.counter++;
+            mv = this.cv.visitMethod( a,
+                                      n,
+                                      desc,
+                                      signature,
+                                      exceptions );
+
+            if ( this.clinit == null ) {
+                this.clinit = this.cv.visitMethod( a,
+                                                   name,
+                                                   desc,
+                                                   null,
+                                                   null );
+            }
+            this.clinit.visitMethodInsn( Opcodes.INVOKESTATIC,
+                                         this.name,
+                                         n,
+                                         desc );
+        } else {
+            mv = this.cv.visitMethod( access,
+                                      name,
+                                      desc,
+                                      signature,
+                                      exceptions );
+        }
+        return mv;
+    }
+
+    public void visitEnd() {
+        if ( this.clinit != null ) {
+            this.clinit.visitInsn( Opcodes.RETURN );
+            this.clinit.visitMaxs( 0,
+                                   0 );
+        }
+        this.cv.visitEnd();
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/TableSwitchGenerator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/TableSwitchGenerator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/TableSwitchGenerator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,56 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.commons;
+
+import org.drools.asm.Label;
+
+/**
+ * A code generator for switch statements.
+ * 
+ * @author Juozas Baliuka
+ * @author Chris Nokleberg
+ * @author Eric Bruneton
+ */
+public interface TableSwitchGenerator {
+
+    /**
+     * Generates the code for a switch case.
+     * 
+     * @param key the switch case key.
+     * @param end a label that corresponds to the end of the switch statement.
+     */
+    void generateCase(int key,
+                      Label end);
+
+    /**
+     * Generates the code for the default switch case.
+     */
+    void generateDefault();
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/package.html
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/package.html	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/commons/package.html	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,33 @@
+<html>
+<!--
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<body>
+Provides some useful class and method adapters.
+</body>
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/package.html
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/package.html	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/package.html	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,87 @@
+<html>
+<!--
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<body>
+Provides a small and fast bytecode manipulation framework.
+
+<p>
+The <a href="http://www.objectweb.org/asm">ASM</a> framework is organized
+around the {@link org.objectweb.asm.ClassVisitor ClassVisitor}, 
+{@link org.objectweb.asm.FieldVisitor FieldVisitor} and 
+{@link org.objectweb.asm.MethodVisitor MethodVisitor} interfaces, which allow
+one to visit the fields and methods of a class, including the bytecode 
+instructions of each method.
+
+<p>
+In addition to these main interfaces, ASM provides a {@link
+org.objectweb.asm.ClassReader ClassReader} class, that can parse an
+existing class and make a given visitor visit it. ASM also provides
+a {@link org.objectweb.asm.ClassWriter ClassWriter} class, which is
+a visitor that generates Java class files.
+
+<p>
+In order to generate a class from scratch, only the {@link
+org.objectweb.asm.ClassWriter ClassWriter} class is necessary. Indeed,
+in order to generate a class, one must just call its visit<i>XXX</i>
+methods with the appropriate arguments to generate the desired fields
+and methods. See the "helloworld" example in the ASM distribution for
+more details about class generation.
+
+<p>
+In order to modify existing classes, one must use a {@link
+org.objectweb.asm.ClassReader ClassReader} class to analyze
+the original class, a class modifier, and a {@link org.objectweb.asm.ClassWriter
+ClassWriter} to construct the modified class. The class modifier
+is just a {@link org.objectweb.asm.ClassVisitor ClassVisitor}
+that delegates most of the work to another {@link org.objectweb.asm.ClassVisitor
+ClassVisitor}, but that sometimes changes some parameter values,
+or call additional methods, in order to implement the desired
+modification process. In order to make it easier to implement such
+class modifiers, ASM provides the {@link org.objectweb.asm.ClassAdapter
+ClassAdapter} and {@link org.objectweb.asm.MethodAdapter MethodAdapter}
+classes, which implement the {@link org.objectweb.asm.ClassVisitor ClassVisitor} 
+and {@link org.objectweb.asm.MethodVisitor MethodVisitor} interfaces by 
+delegating all work to other visitors. See the "adapt" example in the ASM 
+distribution for more details about class modification.
+
+<p>
+The size of the core ASM library, <tt>asm.jar</tt>, is only 31KB, which is much
+more smaller than
+the size of the <a href="http://jakarta.apache.org/bcel">BCEL</a> library (350KB
+without the class verifier), and than the size of the
+<a href="http://serp.sourceforge.net">SERP</a> library (150KB). ASM is also
+much more faster than these tools. Indeed the overhead of a load time class
+transformation process is of the order of 60% with ASM, 700% or more with BCEL,
+and 1100% or more with SERP (see the <tt>test/perf</tt> directory in the ASM
+distribution)!
+
+ at since ASM 1.3
+</body>
+</html>

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/signature/SignatureReader.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/signature/SignatureReader.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/signature/SignatureReader.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,255 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.signature;
+
+/**
+ * A type signature parser to make a signature visitor visit an existing
+ * signature.
+ * 
+ * @author Thomas Hallgren
+ * @author Eric Bruneton
+ */
+public class SignatureReader {
+
+    /**
+     * The signature to be read.
+     */
+    private final String signature;
+
+    /**
+     * Constructs a {@link SignatureReader} for the given signature.
+     * 
+     * @param signature A <i>ClassSignature</i>, <i>MethodTypeSignature</i>,
+     *        or <i>FieldTypeSignature</i>.
+     */
+    public SignatureReader(final String signature) {
+        this.signature = signature;
+    }
+
+    /**
+     * Makes the given visitor visit the signature of this
+     * {@link SignatureReader}. This signature is the one specified in the
+     * constructor (see {@link #SignatureReader(String) SignatureReader}). This
+     * method is intended to be called on a {@link SignatureReader} that was
+     * created using a <i>ClassSignature</i> (such as the
+     * <code>signature</code> parameter of the
+     * {@link org.drools.asm.ClassVisitor#visit ClassVisitor.visit} method)
+     * or a <i>MethodTypeSignature</i> (such as the <code>signature</code>
+     * parameter of the
+     * {@link org.drools.asm.ClassVisitor#visitMethod ClassVisitor.visitMethod}
+     * method).
+     * 
+     * @param v the visitor that must visit this signature.
+     */
+    public void accept(final SignatureVisitor v) {
+        final String signature = this.signature;
+        final int len = signature.length();
+        int pos;
+        char c;
+
+        if ( signature.charAt( 0 ) == '<' ) {
+            pos = 2;
+            do {
+                final int end = signature.indexOf( ':',
+                                                   pos );
+                v.visitFormalTypeParameter( signature.substring( pos - 1,
+                                                                 end ) );
+                pos = end + 1;
+
+                c = signature.charAt( pos );
+                if ( c == 'L' || c == '[' || c == 'T' ) {
+                    pos = parseType( signature,
+                                     pos,
+                                     v.visitClassBound() );
+                }
+
+                for ( ;; ) {
+                    if ( (c = signature.charAt( pos++ )) == ':' ) {
+                        pos = parseType( signature,
+                                         pos,
+                                         v.visitInterfaceBound() );
+                    } else {
+                        break;
+                    }
+                }
+            } while ( c != '>' );
+        } else {
+            pos = 0;
+        }
+
+        if ( signature.charAt( pos ) == '(' ) {
+            pos = pos + 1;
+            while ( signature.charAt( pos ) != ')' ) {
+                pos = parseType( signature,
+                                 pos,
+                                 v.visitParameterType() );
+            }
+            pos = parseType( signature,
+                             pos + 1,
+                             v.visitReturnType() );
+            while ( pos < len ) {
+                pos = parseType( signature,
+                                 pos + 1,
+                                 v.visitExceptionType() );
+            }
+        } else {
+            pos = parseType( signature,
+                             pos,
+                             v.visitSuperclass() );
+            while ( pos < len ) {
+                pos = parseType( signature,
+                                 pos,
+                                 v.visitInterface() );
+            }
+        }
+    }
+
+    /**
+     * Makes the given visitor visit the signature of this
+     * {@link SignatureReader}. This signature is the one specified in the
+     * constructor (see {@link #SignatureReader(String) SignatureReader}). This
+     * method is intended to be called on a {@link SignatureReader} that was
+     * created using a <i>FieldTypeSignature</i>, such as the
+     * <code>signature</code> parameter of the
+     * {@link org.drools.asm.ClassVisitor#visitField 
+     * ClassVisitor.visitField} or {@link 
+     * org.drools.asm.MethodVisitor#visitLocalVariable
+     * MethodVisitor.visitLocalVariable} methods.
+     * 
+     * @param v the visitor that must visit this signature.
+     */
+    public void acceptType(final SignatureVisitor v) {
+        parseType( this.signature,
+                   0,
+                   v );
+    }
+
+    /**
+     * Parses a field type signature and makes the given visitor visit it.
+     * 
+     * @param signature a string containing the signature that must be parsed.
+     * @param pos index of the first character of the signature to parsed.
+     * @param v the visitor that must visit this signature.
+     * @return the index of the first character after the parsed signature.
+     */
+    private static int parseType(final String signature,
+                                 int pos,
+                                 final SignatureVisitor v) {
+        char c;
+        int start, end;
+        boolean visited, inner;
+        String name;
+
+        switch ( c = signature.charAt( pos++ ) ) {
+            case 'Z' :
+            case 'C' :
+            case 'B' :
+            case 'S' :
+            case 'I' :
+            case 'F' :
+            case 'J' :
+            case 'D' :
+            case 'V' :
+                v.visitBaseType( c );
+                return pos;
+
+            case '[' :
+                return parseType( signature,
+                                  pos,
+                                  v.visitArrayType() );
+
+            case 'T' :
+                end = signature.indexOf( ';',
+                                         pos );
+                v.visitTypeVariable( signature.substring( pos,
+                                                          end ) );
+                return end + 1;
+
+            default : // case 'L':
+                start = pos;
+                visited = false;
+                inner = false;
+                for ( ;; ) {
+                    switch ( c = signature.charAt( pos++ ) ) {
+                        case '.' :
+                        case ';' :
+                            if ( !visited ) {
+                                name = signature.substring( start,
+                                                            pos - 1 );
+                                if ( inner ) {
+                                    v.visitInnerClassType( name );
+                                } else {
+                                    v.visitClassType( name );
+                                }
+                            }
+                            if ( c == ';' ) {
+                                v.visitEnd();
+                                return pos;
+                            }
+                            start = pos;
+                            visited = false;
+                            inner = true;
+                            break;
+
+                        case '<' :
+                            name = signature.substring( start,
+                                                        pos - 1 );
+                            if ( inner ) {
+                                v.visitInnerClassType( name );
+                            } else {
+                                v.visitClassType( name );
+                            }
+                            visited = true;
+                            top : for ( ;; ) {
+                                switch ( c = signature.charAt( pos ) ) {
+                                    case '>' :
+                                        break top;
+                                    case '*' :
+                                        ++pos;
+                                        v.visitTypeArgument();
+                                        break;
+                                    case '+' :
+                                    case '-' :
+                                        pos = parseType( signature,
+                                                         pos + 1,
+                                                         v.visitTypeArgument( c ) );
+                                        break;
+                                    default :
+                                        pos = parseType( signature,
+                                                         pos,
+                                                         v.visitTypeArgument( '=' ) );
+                                        break;
+                                }
+                            }
+                    }
+                }
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/signature/SignatureVisitor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/signature/SignatureVisitor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/signature/SignatureVisitor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,185 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.signature;
+
+/**
+ * A visitor to visit a generic signature. The methods of this interface must be
+ * called in one of the three following orders (the last one is the only valid
+ * order for a {@link SignatureVisitor} that is returned by a method of this
+ * interface): <ul> <li><i>ClassSignature</i> = (
+ * <tt>visitFormalTypeParameter</tt> 
+ *   <tt>visitClassBound</tt>?
+ * <tt>visitInterfaceBound</tt>* )* ( <tt>visitSuperClass</tt> 
+ *   <tt>visitInterface</tt>* )</li>
+ * <li><i>MethodSignature</i> = ( <tt>visitFormalTypeParameter</tt> 
+ *   <tt>visitClassBound</tt>?
+ * <tt>visitInterfaceBound</tt>* )* ( <tt>visitParameterType</tt>*
+ * <tt>visitReturnType</tt> 
+ *   <tt>visitExceptionType</tt>* )</li> <li><i>TypeSignature</i> =
+ * <tt>visitBaseType</tt> | <tt>visitTypeVariable</tt> |
+ * <tt>visitArrayType</tt> | (
+ * <tt>visitClassType</tt> <tt>visitTypeArgument</tt>* (
+ * <tt>visitInnerClassType</tt> <tt>visitTypeArgument</tt>* )*
+ * <tt>visitEnd</tt> ) )</li> </ul>
+ * 
+ * @author Thomas Hallgren
+ * @author Eric Bruneton
+ */
+public interface SignatureVisitor {
+
+    /**
+     * Wildcard for an "extends" type argument.
+     */
+    char EXTENDS    = '+';
+
+    /**
+     * Wildcard for a "super" type argument.
+     */
+    char SUPER      = '-';
+
+    /**
+     * Wildcard for a normal type argument.
+     */
+    char INSTANCEOF = '=';
+
+    /**
+     * Visits a formal type parameter.
+     * 
+     * @param name the name of the formal parameter.
+     */
+    void visitFormalTypeParameter(String name);
+
+    /**
+     * Visits the class bound of the last visited formal type parameter.
+     * 
+     * @return a non null visitor to visit the signature of the class bound.
+     */
+    SignatureVisitor visitClassBound();
+
+    /**
+     * Visits an interface bound of the last visited formal type parameter.
+     * 
+     * @return a non null visitor to visit the signature of the interface bound.
+     */
+    SignatureVisitor visitInterfaceBound();
+
+    /**
+     * Visits the type of the super class.
+     * 
+     * @return a non null visitor to visit the signature of the super class
+     *         type.
+     */
+    SignatureVisitor visitSuperclass();
+
+    /**
+     * Visits the type of an interface implemented by the class.
+     * 
+     * @return a non null visitor to visit the signature of the interface type.
+     */
+    SignatureVisitor visitInterface();
+
+    /**
+     * Visits the type of a method parameter.
+     * 
+     * @return a non null visitor to visit the signature of the parameter type.
+     */
+    SignatureVisitor visitParameterType();
+
+    /**
+     * Visits the return type of the method.
+     * 
+     * @return a non null visitor to visit the signature of the return type.
+     */
+    SignatureVisitor visitReturnType();
+
+    /**
+     * Visits the type of a method exception.
+     * 
+     * @return a non null visitor to visit the signature of the exception type.
+     */
+    SignatureVisitor visitExceptionType();
+
+    /**
+     * Visits a signature corresponding to a primitive type.
+     * 
+     * @param descriptor the descriptor of the primitive type, or 'V' for
+     *        <tt>void</tt>.
+     */
+    void visitBaseType(char descriptor);
+
+    /**
+     * Visits a signature corresponding to a type variable.
+     * 
+     * @param name the name of the type variable.
+     */
+    void visitTypeVariable(String name);
+
+    /**
+     * Visits a signature corresponding to an array type.
+     * 
+     * @return a non null visitor to visit the signature of the array element
+     *         type.
+     */
+    SignatureVisitor visitArrayType();
+
+    /**
+     * Starts the visit of a signature corresponding to a class or interface
+     * type.
+     * 
+     * @param name the internal name of the class or interface.
+     */
+    void visitClassType(String name);
+
+    /**
+     * Visits an inner class.
+     * 
+     * @param name the local name of the inner class in its enclosing class.
+     */
+    void visitInnerClassType(String name);
+
+    /**
+     * Visits an unbounded type argument of the last visited class or inner
+     * class type.
+     */
+    void visitTypeArgument();
+
+    /**
+     * Visits a type argument of the last visited class or inner class type.
+     * 
+     * @param wildcard '+', '-' or '='.
+     * @return a non null visitor to visit the signature of the type argument.
+     */
+    SignatureVisitor visitTypeArgument(char wildcard);
+
+    /**
+     * Ends the visit of a signature corresponding to a class or interface type.
+     */
+    void visitEnd();
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/signature/SignatureWriter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/signature/SignatureWriter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/signature/SignatureWriter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,209 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.signature;
+
+/**
+ * A signature visitor that generates signatures in string format.
+ * 
+ * @author Thomas Hallgren
+ * @author Eric Bruneton
+ */
+public class SignatureWriter
+    implements
+    SignatureVisitor {
+
+    /**
+     * Buffer used to construct the signature.
+     */
+    private final StringBuffer buf = new StringBuffer();
+
+    /**
+     * Indicates if the signature contains formal type parameters.
+     */
+    private boolean            hasFormals;
+
+    /**
+     * Indicates if the signature contains method parameter types.
+     */
+    private boolean            hasParameters;
+
+    /**
+     * Stack used to keep track of class types that have arguments. Each element
+     * of this stack is a boolean encoded in one bit. The top of the stack is
+     * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping =
+     * /2.
+     */
+    private int                argumentStack;
+
+    /**
+     * Constructs a new {@link SignatureWriter} object.
+     */
+    public SignatureWriter() {
+    }
+
+    // ------------------------------------------------------------------------
+    // Implementation of the SignatureVisitor interface
+    // ------------------------------------------------------------------------
+
+    public void visitFormalTypeParameter(final String name) {
+        if ( !this.hasFormals ) {
+            this.hasFormals = true;
+            this.buf.append( '<' );
+        }
+        this.buf.append( name );
+        this.buf.append( ':' );
+    }
+
+    public SignatureVisitor visitClassBound() {
+        return this;
+    }
+
+    public SignatureVisitor visitInterfaceBound() {
+        this.buf.append( ':' );
+        return this;
+    }
+
+    public SignatureVisitor visitSuperclass() {
+        endFormals();
+        return this;
+    }
+
+    public SignatureVisitor visitInterface() {
+        return this;
+    }
+
+    public SignatureVisitor visitParameterType() {
+        endFormals();
+        if ( !this.hasParameters ) {
+            this.hasParameters = true;
+            this.buf.append( '(' );
+        }
+        return this;
+    }
+
+    public SignatureVisitor visitReturnType() {
+        endFormals();
+        if ( !this.hasParameters ) {
+            this.buf.append( '(' );
+        }
+        this.buf.append( ')' );
+        return this;
+    }
+
+    public SignatureVisitor visitExceptionType() {
+        this.buf.append( '^' );
+        return this;
+    }
+
+    public void visitBaseType(final char descriptor) {
+        this.buf.append( descriptor );
+    }
+
+    public void visitTypeVariable(final String name) {
+        this.buf.append( 'T' );
+        this.buf.append( name );
+        this.buf.append( ';' );
+    }
+
+    public SignatureVisitor visitArrayType() {
+        this.buf.append( '[' );
+        return this;
+    }
+
+    public void visitClassType(final String name) {
+        this.buf.append( 'L' );
+        this.buf.append( name );
+        this.argumentStack *= 2;
+    }
+
+    public void visitInnerClassType(final String name) {
+        endArguments();
+        this.buf.append( '.' );
+        this.buf.append( name );
+        this.argumentStack *= 2;
+    }
+
+    public void visitTypeArgument() {
+        if ( this.argumentStack % 2 == 0 ) {
+            ++this.argumentStack;
+            this.buf.append( '<' );
+        }
+        this.buf.append( '*' );
+    }
+
+    public SignatureVisitor visitTypeArgument(final char wildcard) {
+        if ( this.argumentStack % 2 == 0 ) {
+            ++this.argumentStack;
+            this.buf.append( '<' );
+        }
+        if ( wildcard != '=' ) {
+            this.buf.append( wildcard );
+        }
+        return this;
+    }
+
+    public void visitEnd() {
+        endArguments();
+        this.buf.append( ';' );
+    }
+
+    /**
+     * Returns the signature that was built by this signature writer.
+     * 
+     * @return the signature that was built by this signature writer.
+     */
+    public String toString() {
+        return this.buf.toString();
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Ends the formal type parameters section of the signature.
+     */
+    private void endFormals() {
+        if ( this.hasFormals ) {
+            this.hasFormals = false;
+            this.buf.append( '>' );
+        }
+    }
+
+    /**
+     * Ends the type arguments of a class or inner class type.
+     */
+    private void endArguments() {
+        if ( this.argumentStack % 2 == 1 ) {
+            this.buf.append( '>' );
+        }
+        this.argumentStack /= 2;
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/signature/package.html
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/signature/package.html	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/signature/package.html	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,36 @@
+<html>
+<!--
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<body>
+Provides support for type signatures.
+
+ at since ASM 2.0
+</body>
+</html>

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/ASMifierAbstractVisitor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/ASMifierAbstractVisitor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/ASMifierAbstractVisitor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,224 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.util;
+
+import java.util.HashMap;
+
+import org.drools.asm.AnnotationVisitor;
+import org.drools.asm.Attribute;
+import org.drools.asm.Type;
+import org.drools.asm.util.attrs.ASMifiable;
+
+/**
+ * An abstract ASMifier visitor.
+ * 
+ * @author Eric Bruneton
+ */
+public class ASMifierAbstractVisitor extends AbstractVisitor {
+
+    /**
+     * The name of the variable for this visitor in the produced code.
+     */
+    protected String name;
+
+    /**
+     * The label names. This map associates String values to Label keys. It is
+     * used only in ASMifierMethodVisitor.
+     */
+    HashMap          labelNames;
+
+    /**
+     * Constructs a new {@link ASMifierAbstractVisitor}.
+     * 
+     * @param name the name of the variable for this visitor in the produced
+     *        code.
+     */
+    protected ASMifierAbstractVisitor(final String name) {
+        this.name = name;
+    }
+
+    /**
+     * Prints the ASM code that generates the given annotation.
+     * 
+     * @param desc the class descriptor of the annotation class.
+     * @param visible <tt>true</tt> if the annotation is visible at runtime.
+     * @return a visitor to visit the annotation values.
+     */
+    public AnnotationVisitor visitAnnotation(final String desc,
+                                             final boolean visible) {
+        this.buf.setLength( 0 );
+        this.buf.append( "{\n" ).append( "av0 = " ).append( this.name ).append( ".visitAnnotation(" );
+        appendConstant( desc );
+        this.buf.append( ", " ).append( visible ).append( ");\n" );
+        this.text.add( this.buf.toString() );
+        final ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor( 0 );
+        this.text.add( av.getText() );
+        this.text.add( "}\n" );
+        return av;
+    }
+
+    /**
+     * Prints the ASM code that generates the given attribute.
+     * 
+     * @param attr an attribute.
+     */
+    public void visitAttribute(final Attribute attr) {
+        this.buf.setLength( 0 );
+        if ( attr instanceof ASMifiable ) {
+            this.buf.append( "{\n" );
+            this.buf.append( "// ATTRIBUTE\n" );
+            ((ASMifiable) attr).asmify( this.buf,
+                                        "attr",
+                                        this.labelNames );
+            this.buf.append( this.name ).append( ".visitAttribute(attr);\n" );
+            this.buf.append( "}\n" );
+        } else {
+            this.buf.append( "// WARNING! skipped a non standard attribute of type \"" );
+            this.buf.append( attr.type ).append( "\"\n" );
+        }
+        this.text.add( this.buf.toString() );
+    }
+
+    /**
+     * Prints the ASM code to end the visit.
+     */
+    public void visitEnd() {
+        this.buf.setLength( 0 );
+        this.buf.append( this.name ).append( ".visitEnd();\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    /**
+     * Appends a string representation of the given constant to the given
+     * buffer.
+     * 
+     * @param cst an {@link Integer}, {@link Float}, {@link Long},
+     *        {@link Double} or {@link String} object. May be <tt>null</tt>.
+     */
+    void appendConstant(final Object cst) {
+        appendConstant( this.buf,
+                        cst );
+    }
+
+    /**
+     * Appends a string representation of the given constant to the given
+     * buffer.
+     * 
+     * @param buf a string buffer.
+     * @param cst an {@link Integer}, {@link Float}, {@link Long},
+     *        {@link Double} or {@link String} object. May be <tt>null</tt>.
+     */
+    static void appendConstant(final StringBuffer buf,
+                               final Object cst) {
+        if ( cst == null ) {
+            buf.append( "null" );
+        } else if ( cst instanceof String ) {
+            appendString( buf,
+                          (String) cst );
+        } else if ( cst instanceof Type ) {
+            buf.append( "Type.getType(\"" );
+            buf.append( ((Type) cst).getDescriptor() );
+            buf.append( "\")" );
+        } else if ( cst instanceof Byte ) {
+            buf.append( "new Byte((byte)" ).append( cst ).append( ")" );
+        } else if ( cst instanceof Boolean ) {
+            buf.append( "new Boolean(" ).append( cst ).append( ")" );
+        } else if ( cst instanceof Short ) {
+            buf.append( "new Short((short)" ).append( cst ).append( ")" );
+        } else if ( cst instanceof Character ) {
+            final int c = ((Character) cst).charValue();
+            buf.append( "new Character((char)" ).append( c ).append( ")" );
+        } else if ( cst instanceof Integer ) {
+            buf.append( "new Integer(" ).append( cst ).append( ")" );
+        } else if ( cst instanceof Float ) {
+            buf.append( "new Float(\"" ).append( cst ).append( "\")" );
+        } else if ( cst instanceof Long ) {
+            buf.append( "new Long(" ).append( cst ).append( "L)" );
+        } else if ( cst instanceof Double ) {
+            buf.append( "new Double(\"" ).append( cst ).append( "\")" );
+        } else if ( cst instanceof byte[] ) {
+            final byte[] v = (byte[]) cst;
+            buf.append( "new byte[] {" );
+            for ( int i = 0; i < v.length; i++ ) {
+                buf.append( i == 0 ? "" : "," ).append( v[i] );
+            }
+            buf.append( "}" );
+        } else if ( cst instanceof boolean[] ) {
+            final boolean[] v = (boolean[]) cst;
+            buf.append( "new boolean[] {" );
+            for ( int i = 0; i < v.length; i++ ) {
+                buf.append( i == 0 ? "" : "," ).append( v[i] );
+            }
+            buf.append( "}" );
+        } else if ( cst instanceof short[] ) {
+            final short[] v = (short[]) cst;
+            buf.append( "new short[] {" );
+            for ( int i = 0; i < v.length; i++ ) {
+                buf.append( i == 0 ? "" : "," ).append( "(short)" ).append( v[i] );
+            }
+            buf.append( "}" );
+        } else if ( cst instanceof char[] ) {
+            final char[] v = (char[]) cst;
+            buf.append( "new char[] {" );
+            for ( int i = 0; i < v.length; i++ ) {
+                buf.append( i == 0 ? "" : "," ).append( "(char)" ).append( (int) v[i] );
+            }
+            buf.append( "}" );
+        } else if ( cst instanceof int[] ) {
+            final int[] v = (int[]) cst;
+            buf.append( "new int[] {" );
+            for ( int i = 0; i < v.length; i++ ) {
+                buf.append( i == 0 ? "" : "," ).append( v[i] );
+            }
+            buf.append( "}" );
+        } else if ( cst instanceof long[] ) {
+            final long[] v = (long[]) cst;
+            buf.append( "new long[] {" );
+            for ( int i = 0; i < v.length; i++ ) {
+                buf.append( i == 0 ? "" : "," ).append( v[i] ).append( "L" );
+            }
+            buf.append( "}" );
+        } else if ( cst instanceof float[] ) {
+            final float[] v = (float[]) cst;
+            buf.append( "new float[] {" );
+            for ( int i = 0; i < v.length; i++ ) {
+                buf.append( i == 0 ? "" : "," ).append( v[i] ).append( "f" );
+            }
+            buf.append( "}" );
+        } else if ( cst instanceof double[] ) {
+            final double[] v = (double[]) cst;
+            buf.append( "new double[] {" );
+            for ( int i = 0; i < v.length; i++ ) {
+                buf.append( i == 0 ? "" : "," ).append( v[i] ).append( "d" );
+            }
+            buf.append( "}" );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/ASMifierAnnotationVisitor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/ASMifierAnnotationVisitor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/ASMifierAnnotationVisitor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,132 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.util;
+
+import org.drools.asm.AnnotationVisitor;
+
+/**
+ * An {@link AnnotationVisitor} that prints the ASM code that generates the
+ * annotations it visits.
+ * 
+ * @author Eric Bruneton
+ */
+public class ASMifierAnnotationVisitor extends AbstractVisitor
+    implements
+    AnnotationVisitor {
+
+    /**
+     * Identifier of the annotation visitor variable in the produced code.
+     */
+    protected final int id;
+
+    /**
+     * Constructs a new {@link ASMifierAnnotationVisitor}.
+     * 
+     * @param id identifier of the annotation visitor variable in the produced
+     *        code.
+     */
+    public ASMifierAnnotationVisitor(final int id) {
+        this.id = id;
+    }
+
+    // ------------------------------------------------------------------------
+    // Implementation of the AnnotationVisitor interface
+    // ------------------------------------------------------------------------
+
+    public void visit(final String name,
+                      final Object value) {
+        this.buf.setLength( 0 );
+        this.buf.append( "av" ).append( this.id ).append( ".visit(" );
+        ASMifierAbstractVisitor.appendConstant( this.buf,
+                                                name );
+        this.buf.append( ", " );
+        ASMifierAbstractVisitor.appendConstant( this.buf,
+                                                value );
+        this.buf.append( ");\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    public void visitEnum(final String name,
+                          final String desc,
+                          final String value) {
+        this.buf.setLength( 0 );
+        this.buf.append( "av" ).append( this.id ).append( ".visitEnum(" );
+        ASMifierAbstractVisitor.appendConstant( this.buf,
+                                                name );
+        this.buf.append( ", " );
+        ASMifierAbstractVisitor.appendConstant( this.buf,
+                                                desc );
+        this.buf.append( ", " );
+        ASMifierAbstractVisitor.appendConstant( this.buf,
+                                                value );
+        this.buf.append( ");\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    public AnnotationVisitor visitAnnotation(final String name,
+                                             final String desc) {
+        this.buf.setLength( 0 );
+        this.buf.append( "{\n" );
+        this.buf.append( "AnnotationVisitor av" ).append( this.id + 1 ).append( " = av" );
+        this.buf.append( this.id ).append( ".visitAnnotation(" );
+        ASMifierAbstractVisitor.appendConstant( this.buf,
+                                                name );
+        this.buf.append( ", " );
+        ASMifierAbstractVisitor.appendConstant( this.buf,
+                                                desc );
+        this.buf.append( ");\n" );
+        this.text.add( this.buf.toString() );
+        final ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor( this.id + 1 );
+        this.text.add( av.getText() );
+        this.text.add( "}\n" );
+        return av;
+    }
+
+    public AnnotationVisitor visitArray(final String name) {
+        this.buf.setLength( 0 );
+        this.buf.append( "{\n" );
+        this.buf.append( "AnnotationVisitor av" ).append( this.id + 1 ).append( " = av" );
+        this.buf.append( this.id ).append( ".visitArray(" );
+        ASMifierAbstractVisitor.appendConstant( this.buf,
+                                                name );
+        this.buf.append( ");\n" );
+        this.text.add( this.buf.toString() );
+        final ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor( this.id + 1 );
+        this.text.add( av.getText() );
+        this.text.add( "}\n" );
+        return av;
+    }
+
+    public void visitEnd() {
+        this.buf.setLength( 0 );
+        this.buf.append( "av" ).append( this.id ).append( ".visitEnd();\n" );
+        this.text.add( this.buf.toString() );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/ASMifierClassVisitor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/ASMifierClassVisitor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/ASMifierClassVisitor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,581 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.util;
+
+import java.io.FileInputStream;
+import java.io.PrintWriter;
+
+import org.drools.asm.AnnotationVisitor;
+import org.drools.asm.ClassReader;
+import org.drools.asm.ClassVisitor;
+import org.drools.asm.FieldVisitor;
+import org.drools.asm.MethodVisitor;
+import org.drools.asm.Opcodes;
+import org.drools.asm.Type;
+
+/**
+ * A {@link ClassVisitor} that prints the ASM code that generates the classes it
+ * visits. This class visitor can be used to quickly write ASM code to generate
+ * some given bytecode: <ul> <li>write the Java source code equivalent to the
+ * bytecode you want to generate;</li> <li>compile it with <tt>javac</tt>;</li>
+ * <li>make a {@link ASMifierClassVisitor} visit this compiled class (see the
+ * {@link #main main} method);</li> <li>edit the generated source code, if
+ * necessary.</li> </ul> The source code printed when visiting the
+ * <tt>Hello</tt> class is the following: <p> <blockquote>
+ * 
+ * <pre>
+ * import org.objectweb.asm.*;
+ * 
+ * public class HelloDump implements Opcodes {
+ * 
+ *     public static byte[] dump() throws Exception {
+ * 
+ *         ClassWriter cw = new ClassWriter(false);
+ *         FieldVisitor fv;
+ *         MethodVisitor mv;
+ *         AnnotationVisitor av0;
+ * 
+ *         cw.visit(49,
+ *                 ACC_PUBLIC + ACC_SUPER,
+ *                 &quot;Hello&quot;,
+ *                 null,
+ *                 &quot;java/lang/Object&quot;,
+ *                 null);
+ * 
+ *         cw.visitSource(&quot;Hello.java&quot;, null);
+ * 
+ *         {
+ *             mv = cw.visitMethod(ACC_PUBLIC, &quot;&lt;init&gt;&quot;, &quot;()V&quot;, null, null);
+ *             mv.visitVarInsn(ALOAD, 0);
+ *             mv.visitMethodInsn(INVOKESPECIAL,
+ *                     &quot;java/lang/Object&quot;,
+ *                     &quot;&lt;init&gt;&quot;,
+ *                     &quot;()V&quot;);
+ *             mv.visitInsn(RETURN);
+ *             mv.visitMaxs(1, 1);
+ *             mv.visitEnd();
+ *         }
+ *         {
+ *             mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC,
+ *                     &quot;main&quot;,
+ *                     &quot;([Ljava/lang/String;)V&quot;,
+ *                     null,
+ *                     null);
+ *             mv.visitFieldInsn(GETSTATIC,
+ *                     &quot;java/lang/System&quot;,
+ *                     &quot;out&quot;,
+ *                     &quot;Ljava/io/PrintStream;&quot;);
+ *             mv.visitLdcInsn(&quot;hello&quot;);
+ *             mv.visitMethodInsn(INVOKEVIRTUAL,
+ *                     &quot;java/io/PrintStream&quot;,
+ *                     &quot;println&quot;,
+ *                     &quot;(Ljava/lang/String;)V&quot;);
+ *             mv.visitInsn(RETURN);
+ *             mv.visitMaxs(2, 1);
+ *             mv.visitEnd();
+ *         }
+ *         cw.visitEnd();
+ * 
+ *         return cw.toByteArray();
+ *     }
+ * }
+ * 
+ * </pre>
+ * 
+ * </blockquote> where <tt>Hello</tt> is defined by: <p> <blockquote>
+ * 
+ * <pre>
+ * public class Hello {
+ * 
+ *     public static void main(String[] args) {
+ *         System.out.println(&quot;hello&quot;);
+ *     }
+ * }
+ * </pre>
+ * 
+ * </blockquote>
+ * 
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class ASMifierClassVisitor extends ASMifierAbstractVisitor
+    implements
+    ClassVisitor {
+
+    /**
+     * Pseudo access flag used to distinguish class access flags.
+     */
+    private final static int    ACCESS_CLASS = 262144;
+
+    /**
+     * Pseudo access flag used to distinguish field access flags.
+     */
+    private final static int    ACCESS_FIELD = 524288;
+
+    /**
+     * Pseudo access flag used to distinguish inner class flags.
+     */
+    private static final int    ACCESS_INNER = 1048576;
+
+    /**
+     * The print writer to be used to print the class.
+     */
+    protected final PrintWriter pw;
+
+    /**
+     * Prints the ASM source code to generate the given class to the standard
+     * output. <p> Usage: ASMifierClassVisitor [-debug] &lt;fully qualified
+     * class name or class file name&gt;
+     * 
+     * @param args the command line arguments.
+     * 
+     * @throws Exception if the class cannot be found, or if an IO exception
+     *         occurs.
+     */
+    public static void main(final String[] args) throws Exception {
+        int i = 0;
+        boolean skipDebug = true;
+
+        boolean ok = true;
+        if ( args.length < 1 || args.length > 2 ) {
+            ok = false;
+        }
+        if ( ok && args[0].equals( "-debug" ) ) {
+            i = 1;
+            skipDebug = false;
+            if ( args.length != 2 ) {
+                ok = false;
+            }
+        }
+        if ( !ok ) {
+            System.err.println( "Prints the ASM code to generate the given class." );
+            System.err.println( "Usage: ASMifierClassVisitor [-debug] " + "<fully qualified class name or class file name>" );
+            return;
+        }
+        ClassReader cr;
+        if ( args[i].endsWith( ".class" ) || args[i].indexOf( '\\' ) > -1 || args[i].indexOf( '/' ) > -1 ) {
+            cr = new ClassReader( new FileInputStream( args[i] ) );
+        } else {
+            cr = new ClassReader( args[i] );
+        }
+        cr.accept( new ASMifierClassVisitor( new PrintWriter( System.out ) ),
+                   getDefaultAttributes(),
+                   skipDebug );
+    }
+
+    /**
+     * Constructs a new {@link ASMifierClassVisitor} object.
+     * 
+     * @param pw the print writer to be used to print the class.
+     */
+    public ASMifierClassVisitor(final PrintWriter pw) {
+        super( "cw" );
+        this.pw = pw;
+    }
+
+    // ------------------------------------------------------------------------
+    // Implementation of the ClassVisitor interface
+    // ------------------------------------------------------------------------
+
+    public void visit(final int version,
+                      final int access,
+                      final String name,
+                      final String signature,
+                      final String superName,
+                      final String[] interfaces) {
+        String simpleName;
+        final int n = name.lastIndexOf( '/' );
+        if ( n != -1 ) {
+            this.text.add( "package asm." + name.substring( 0,
+                                                            n ).replace( '/',
+                                                                         '.' ) + ";\n" );
+            simpleName = name.substring( n + 1 );
+        } else {
+            simpleName = name;
+        }
+        this.text.add( "import java.util.*;\n" );
+        this.text.add( "import org.objectweb.asm.*;\n" );
+        this.text.add( "import org.objectweb.asm.attrs.*;\n" );
+        this.text.add( "public class " + simpleName + "Dump implements Opcodes {\n\n" );
+        this.text.add( "public static byte[] dump () throws Exception {\n\n" );
+        this.text.add( "ClassWriter cw = new ClassWriter(false);\n" );
+        this.text.add( "FieldVisitor fv;\n" );
+        this.text.add( "MethodVisitor mv;\n" );
+        this.text.add( "AnnotationVisitor av0;\n\n" );
+
+        this.buf.setLength( 0 );
+        this.buf.append( "cw.visit(" );
+        switch ( version ) {
+            case Opcodes.V1_1 :
+                this.buf.append( "V1_1" );
+                break;
+            case Opcodes.V1_2 :
+                this.buf.append( "V1_2" );
+                break;
+            case Opcodes.V1_3 :
+                this.buf.append( "V1_3" );
+                break;
+            case Opcodes.V1_4 :
+                this.buf.append( "V1_4" );
+                break;
+            case Opcodes.V1_5 :
+                this.buf.append( "V1_5" );
+                break;
+            case Opcodes.V1_6 :
+                this.buf.append( "V1_6" );
+                break;
+            default :
+                this.buf.append( version );
+                break;
+        }
+        this.buf.append( ", " );
+        appendAccess( access | ASMifierClassVisitor.ACCESS_CLASS );
+        this.buf.append( ", " );
+        appendConstant( name );
+        this.buf.append( ", " );
+        appendConstant( signature );
+        this.buf.append( ", " );
+        appendConstant( superName );
+        this.buf.append( ", " );
+        if ( interfaces != null && interfaces.length > 0 ) {
+            this.buf.append( "new String[] {" );
+            for ( int i = 0; i < interfaces.length; ++i ) {
+                this.buf.append( i == 0 ? " " : ", " );
+                appendConstant( interfaces[i] );
+            }
+            this.buf.append( " }" );
+        } else {
+            this.buf.append( "null" );
+        }
+        this.buf.append( ");\n\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    public void visitSource(final String file,
+                            final String debug) {
+        this.buf.setLength( 0 );
+        this.buf.append( "cw.visitSource(" );
+        appendConstant( file );
+        this.buf.append( ", " );
+        appendConstant( debug );
+        this.buf.append( ");\n\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    public void visitOuterClass(final String owner,
+                                final String name,
+                                final String desc) {
+        this.buf.setLength( 0 );
+        this.buf.append( "cw.visitOuterClass(" );
+        appendConstant( owner );
+        this.buf.append( ", " );
+        appendConstant( name );
+        this.buf.append( ", " );
+        appendConstant( desc );
+        this.buf.append( ");\n\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    public void visitInnerClass(final String name,
+                                final String outerName,
+                                final String innerName,
+                                final int access) {
+        this.buf.setLength( 0 );
+        this.buf.append( "cw.visitInnerClass(" );
+        appendConstant( name );
+        this.buf.append( ", " );
+        appendConstant( outerName );
+        this.buf.append( ", " );
+        appendConstant( innerName );
+        this.buf.append( ", " );
+        appendAccess( access | ASMifierClassVisitor.ACCESS_INNER );
+        this.buf.append( ");\n\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    public FieldVisitor visitField(final int access,
+                                   final String name,
+                                   final String desc,
+                                   final String signature,
+                                   final Object value) {
+        this.buf.setLength( 0 );
+        this.buf.append( "{\n" );
+        this.buf.append( "fv = cw.visitField(" );
+        appendAccess( access | ASMifierClassVisitor.ACCESS_FIELD );
+        this.buf.append( ", " );
+        appendConstant( name );
+        this.buf.append( ", " );
+        appendConstant( desc );
+        this.buf.append( ", " );
+        appendConstant( signature );
+        this.buf.append( ", " );
+        appendConstant( value );
+        this.buf.append( ");\n" );
+        this.text.add( this.buf.toString() );
+        final ASMifierFieldVisitor aav = new ASMifierFieldVisitor();
+        this.text.add( aav.getText() );
+        this.text.add( "}\n" );
+        return aav;
+    }
+
+    public MethodVisitor visitMethod(final int access,
+                                     final String name,
+                                     final String desc,
+                                     final String signature,
+                                     final String[] exceptions) {
+        this.buf.setLength( 0 );
+        this.buf.append( "{\n" );
+        this.buf.append( "mv = cw.visitMethod(" );
+        appendAccess( access );
+        this.buf.append( ", " );
+        appendConstant( name );
+        this.buf.append( ", " );
+        appendConstant( desc );
+        this.buf.append( ", " );
+        appendConstant( signature );
+        this.buf.append( ", " );
+        if ( exceptions != null && exceptions.length > 0 ) {
+            this.buf.append( "new String[] {" );
+            for ( int i = 0; i < exceptions.length; ++i ) {
+                this.buf.append( i == 0 ? " " : ", " );
+                appendConstant( exceptions[i] );
+            }
+            this.buf.append( " }" );
+        } else {
+            this.buf.append( "null" );
+        }
+        this.buf.append( ");\n" );
+        this.text.add( this.buf.toString() );
+        final ASMifierMethodVisitor acv = new ASMifierMethodVisitor();
+        this.text.add( acv.getText() );
+        this.text.add( "}\n" );
+        return acv;
+    }
+
+    public AnnotationVisitor visitAnnotation(final String desc,
+                                             final boolean visible) {
+        this.buf.setLength( 0 );
+        this.buf.append( "{\n" );
+        this.buf.append( "av0 = cw.visitAnnotation(" );
+        appendConstant( desc );
+        this.buf.append( ", " );
+        this.buf.append( visible );
+        this.buf.append( ");\n" );
+        this.text.add( this.buf.toString() );
+        final ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor( 0 );
+        this.text.add( av.getText() );
+        this.text.add( "}\n" );
+        return av;
+    }
+
+    public void visitEnd() {
+        this.text.add( "cw.visitEnd();\n\n" );
+        this.text.add( "return cw.toByteArray();\n" );
+        this.text.add( "}\n" );
+        this.text.add( "}\n" );
+        printList( this.pw,
+                   this.text );
+        this.pw.flush();
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Appends a string representation of the given access modifiers to {@link
+     * #buf buf}.
+     * 
+     * @param access some access modifiers.
+     */
+    void appendAccess(final int access) {
+        boolean first = true;
+        if ( (access & Opcodes.ACC_PUBLIC) != 0 ) {
+            this.buf.append( "ACC_PUBLIC" );
+            first = false;
+        }
+        if ( (access & Opcodes.ACC_PRIVATE) != 0 ) {
+            if ( !first ) {
+                this.buf.append( " + " );
+            }
+            this.buf.append( "ACC_PRIVATE" );
+            first = false;
+        }
+        if ( (access & Opcodes.ACC_PROTECTED) != 0 ) {
+            if ( !first ) {
+                this.buf.append( " + " );
+            }
+            this.buf.append( "ACC_PROTECTED" );
+            first = false;
+        }
+        if ( (access & Opcodes.ACC_FINAL) != 0 ) {
+            if ( !first ) {
+                this.buf.append( " + " );
+            }
+            this.buf.append( "ACC_FINAL" );
+            first = false;
+        }
+        if ( (access & Opcodes.ACC_STATIC) != 0 ) {
+            if ( !first ) {
+                this.buf.append( " + " );
+            }
+            this.buf.append( "ACC_STATIC" );
+            first = false;
+        }
+        if ( (access & Opcodes.ACC_SYNCHRONIZED) != 0 ) {
+            if ( !first ) {
+                this.buf.append( " + " );
+            }
+            if ( (access & ASMifierClassVisitor.ACCESS_CLASS) != 0 ) {
+                this.buf.append( "ACC_SUPER" );
+            } else {
+                this.buf.append( "ACC_SYNCHRONIZED" );
+            }
+            first = false;
+        }
+        if ( (access & Opcodes.ACC_VOLATILE) != 0 && (access & ASMifierClassVisitor.ACCESS_FIELD) != 0 ) {
+            if ( !first ) {
+                this.buf.append( " + " );
+            }
+            this.buf.append( "ACC_VOLATILE" );
+            first = false;
+        }
+        if ( (access & Opcodes.ACC_BRIDGE) != 0 && (access & ASMifierClassVisitor.ACCESS_CLASS) == 0 && (access & ASMifierClassVisitor.ACCESS_FIELD) == 0 ) {
+            if ( !first ) {
+                this.buf.append( " + " );
+            }
+            this.buf.append( "ACC_BRIDGE" );
+            first = false;
+        }
+        if ( (access & Opcodes.ACC_VARARGS) != 0 && (access & ASMifierClassVisitor.ACCESS_CLASS) == 0 && (access & ASMifierClassVisitor.ACCESS_FIELD) == 0 ) {
+            if ( !first ) {
+                this.buf.append( " + " );
+            }
+            this.buf.append( "ACC_VARARGS" );
+            first = false;
+        }
+        if ( (access & Opcodes.ACC_TRANSIENT) != 0 && (access & ASMifierClassVisitor.ACCESS_FIELD) != 0 ) {
+            if ( !first ) {
+                this.buf.append( " + " );
+            }
+            this.buf.append( "ACC_TRANSIENT" );
+            first = false;
+        }
+        if ( (access & Opcodes.ACC_NATIVE) != 0 && (access & ASMifierClassVisitor.ACCESS_CLASS) == 0 && (access & ASMifierClassVisitor.ACCESS_FIELD) == 0 ) {
+            if ( !first ) {
+                this.buf.append( " + " );
+            }
+            this.buf.append( "ACC_NATIVE" );
+            first = false;
+        }
+        if ( (access & Opcodes.ACC_ENUM) != 0 && ((access & ASMifierClassVisitor.ACCESS_CLASS) != 0 || (access & ASMifierClassVisitor.ACCESS_FIELD) != 0 || (access & ASMifierClassVisitor.ACCESS_INNER) != 0) ) {
+            if ( !first ) {
+                this.buf.append( " + " );
+            }
+            this.buf.append( "ACC_ENUM" );
+            first = false;
+        }
+        if ( (access & Opcodes.ACC_ANNOTATION) != 0 && ((access & ASMifierClassVisitor.ACCESS_CLASS) != 0) ) {
+            if ( !first ) {
+                this.buf.append( " + " );
+            }
+            this.buf.append( "ACC_ANNOTATION" );
+            first = false;
+        }
+        if ( (access & Opcodes.ACC_ABSTRACT) != 0 ) {
+            if ( !first ) {
+                this.buf.append( " + " );
+            }
+            this.buf.append( "ACC_ABSTRACT" );
+            first = false;
+        }
+        if ( (access & Opcodes.ACC_INTERFACE) != 0 ) {
+            if ( !first ) {
+                this.buf.append( " + " );
+            }
+            this.buf.append( "ACC_INTERFACE" );
+            first = false;
+        }
+        if ( (access & Opcodes.ACC_STRICT) != 0 ) {
+            if ( !first ) {
+                this.buf.append( " + " );
+            }
+            this.buf.append( "ACC_STRICT" );
+            first = false;
+        }
+        if ( (access & Opcodes.ACC_SYNTHETIC) != 0 ) {
+            if ( !first ) {
+                this.buf.append( " + " );
+            }
+            this.buf.append( "ACC_SYNTHETIC" );
+            first = false;
+        }
+        if ( (access & Opcodes.ACC_DEPRECATED) != 0 ) {
+            if ( !first ) {
+                this.buf.append( " + " );
+            }
+            this.buf.append( "ACC_DEPRECATED" );
+            first = false;
+        }
+        if ( first ) {
+            this.buf.append( "0" );
+        }
+    }
+
+    /**
+     * Appends a string representation of the given constant to the given
+     * buffer.
+     * 
+     * @param buf a string buffer.
+     * @param cst an {@link java.lang.Integer Integer}, {@link java.lang.Float
+     *        Float}, {@link java.lang.Long Long},
+     *        {@link java.lang.Double Double} or {@link String String} object.
+     *        May be <tt>null</tt>.
+     */
+    static void appendConstant(final StringBuffer buf,
+                               final Object cst) {
+        if ( cst == null ) {
+            buf.append( "null" );
+        } else if ( cst instanceof String ) {
+            AbstractVisitor.appendString( buf,
+                                          (String) cst );
+        } else if ( cst instanceof Type ) {
+            buf.append( "Type.getType(\"" ).append( ((Type) cst).getDescriptor() ).append( "\")" );
+        } else if ( cst instanceof Integer ) {
+            buf.append( "new Integer(" ).append( cst ).append( ")" );
+        } else if ( cst instanceof Float ) {
+            buf.append( "new Float(\"" ).append( cst ).append( "\")" );
+        } else if ( cst instanceof Long ) {
+            buf.append( "new Long(" ).append( cst ).append( "L)" );
+        } else if ( cst instanceof Double ) {
+            buf.append( "new Double(\"" ).append( cst ).append( "\")" );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/ASMifierFieldVisitor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/ASMifierFieldVisitor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/ASMifierFieldVisitor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,50 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.util;
+
+import org.drools.asm.FieldVisitor;
+
+/**
+ * A {@link FieldVisitor} that prints the ASM code that generates the fields it
+ * visits.
+ * 
+ * @author Eric Bruneton
+ */
+public class ASMifierFieldVisitor extends ASMifierAbstractVisitor
+    implements
+    FieldVisitor {
+
+    /**
+     * Constructs a new {@link ASMifierFieldVisitor}.
+     */
+    public ASMifierFieldVisitor() {
+        super( "fv" );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/ASMifierMethodVisitor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/ASMifierMethodVisitor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/ASMifierMethodVisitor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,317 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.util;
+
+import java.util.HashMap;
+
+import org.drools.asm.AnnotationVisitor;
+import org.drools.asm.Label;
+import org.drools.asm.MethodVisitor;
+import org.drools.asm.Opcodes;
+
+/**
+ * A {@link MethodVisitor} that prints the ASM code that generates the methods
+ * it visits.
+ * 
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class ASMifierMethodVisitor extends ASMifierAbstractVisitor
+    implements
+    MethodVisitor {
+
+    /**
+     * Constructs a new {@link ASMifierMethodVisitor} object.
+     */
+    public ASMifierMethodVisitor() {
+        super( "mv" );
+        this.labelNames = new HashMap();
+    }
+
+    public AnnotationVisitor visitAnnotationDefault() {
+        this.buf.setLength( 0 );
+        this.buf.append( "{\n" ).append( "av0 = mv.visitAnnotationDefault();\n" );
+        this.text.add( this.buf.toString() );
+        final ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor( 0 );
+        this.text.add( av.getText() );
+        this.text.add( "}\n" );
+        return av;
+    }
+
+    public AnnotationVisitor visitParameterAnnotation(final int parameter,
+                                                      final String desc,
+                                                      final boolean visible) {
+        this.buf.setLength( 0 );
+        this.buf.append( "{\n" ).append( "av0 = mv.visitParameterAnnotation(" ).append( parameter ).append( ", " );
+        appendConstant( desc );
+        this.buf.append( ", " ).append( visible ).append( ");\n" );
+        this.text.add( this.buf.toString() );
+        final ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor( 0 );
+        this.text.add( av.getText() );
+        this.text.add( "}\n" );
+        return av;
+    }
+
+    public void visitCode() {
+        this.text.add( "mv.visitCode();\n" );
+    }
+
+    public void visitInsn(final int opcode) {
+        this.buf.setLength( 0 );
+        this.buf.append( "mv.visitInsn(" ).append( AbstractVisitor.OPCODES[opcode] ).append( ");\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    public void visitIntInsn(final int opcode,
+                             final int operand) {
+        this.buf.setLength( 0 );
+        this.buf.append( "mv.visitIntInsn(" ).append( AbstractVisitor.OPCODES[opcode] ).append( ", " ).append( opcode == Opcodes.NEWARRAY ? AbstractVisitor.TYPES[operand] : Integer.toString( operand ) ).append( ");\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    public void visitVarInsn(final int opcode,
+                             final int var) {
+        this.buf.setLength( 0 );
+        this.buf.append( "mv.visitVarInsn(" ).append( AbstractVisitor.OPCODES[opcode] ).append( ", " ).append( var ).append( ");\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    public void visitTypeInsn(final int opcode,
+                              final String desc) {
+        this.buf.setLength( 0 );
+        this.buf.append( "mv.visitTypeInsn(" ).append( AbstractVisitor.OPCODES[opcode] ).append( ", " );
+        appendConstant( desc );
+        this.buf.append( ");\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    public void visitFieldInsn(final int opcode,
+                               final String owner,
+                               final String name,
+                               final String desc) {
+        this.buf.setLength( 0 );
+        this.buf.append( "mv.visitFieldInsn(" ).append( AbstractVisitor.OPCODES[opcode] ).append( ", " );
+        appendConstant( owner );
+        this.buf.append( ", " );
+        appendConstant( name );
+        this.buf.append( ", " );
+        appendConstant( desc );
+        this.buf.append( ");\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    public void visitMethodInsn(final int opcode,
+                                final String owner,
+                                final String name,
+                                final String desc) {
+        this.buf.setLength( 0 );
+        this.buf.append( "mv.visitMethodInsn(" ).append( AbstractVisitor.OPCODES[opcode] ).append( ", " );
+        appendConstant( owner );
+        this.buf.append( ", " );
+        appendConstant( name );
+        this.buf.append( ", " );
+        appendConstant( desc );
+        this.buf.append( ");\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    public void visitJumpInsn(final int opcode,
+                              final Label label) {
+        this.buf.setLength( 0 );
+        declareLabel( label );
+        this.buf.append( "mv.visitJumpInsn(" ).append( AbstractVisitor.OPCODES[opcode] ).append( ", " );
+        appendLabel( label );
+        this.buf.append( ");\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    public void visitLabel(final Label label) {
+        this.buf.setLength( 0 );
+        declareLabel( label );
+        this.buf.append( "mv.visitLabel(" );
+        appendLabel( label );
+        this.buf.append( ");\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    public void visitLdcInsn(final Object cst) {
+        this.buf.setLength( 0 );
+        this.buf.append( "mv.visitLdcInsn(" );
+        appendConstant( cst );
+        this.buf.append( ");\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    public void visitIincInsn(final int var,
+                              final int increment) {
+        this.buf.setLength( 0 );
+        this.buf.append( "mv.visitIincInsn(" ).append( var ).append( ", " ).append( increment ).append( ");\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    public void visitTableSwitchInsn(final int min,
+                                     final int max,
+                                     final Label dflt,
+                                     final Label labels[]) {
+        this.buf.setLength( 0 );
+        for ( int i = 0; i < labels.length; ++i ) {
+            declareLabel( labels[i] );
+        }
+        declareLabel( dflt );
+
+        this.buf.append( "mv.visitTableSwitchInsn(" ).append( min ).append( ", " ).append( max ).append( ", " );
+        appendLabel( dflt );
+        this.buf.append( ", new Label[] {" );
+        for ( int i = 0; i < labels.length; ++i ) {
+            this.buf.append( i == 0 ? " " : ", " );
+            appendLabel( labels[i] );
+        }
+        this.buf.append( " });\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    public void visitLookupSwitchInsn(final Label dflt,
+                                      final int keys[],
+                                      final Label labels[]) {
+        this.buf.setLength( 0 );
+        for ( int i = 0; i < labels.length; ++i ) {
+            declareLabel( labels[i] );
+        }
+        declareLabel( dflt );
+
+        this.buf.append( "mv.visitLookupSwitchInsn(" );
+        appendLabel( dflt );
+        this.buf.append( ", new int[] {" );
+        for ( int i = 0; i < keys.length; ++i ) {
+            this.buf.append( i == 0 ? " " : ", " ).append( keys[i] );
+        }
+        this.buf.append( " }, new Label[] {" );
+        for ( int i = 0; i < labels.length; ++i ) {
+            this.buf.append( i == 0 ? " " : ", " );
+            appendLabel( labels[i] );
+        }
+        this.buf.append( " });\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    public void visitMultiANewArrayInsn(final String desc,
+                                        final int dims) {
+        this.buf.setLength( 0 );
+        this.buf.append( "mv.visitMultiANewArrayInsn(" );
+        appendConstant( desc );
+        this.buf.append( ", " ).append( dims ).append( ");\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    public void visitTryCatchBlock(final Label start,
+                                   final Label end,
+                                   final Label handler,
+                                   final String type) {
+        this.buf.setLength( 0 );
+        declareLabel( start );
+        declareLabel( end );
+        declareLabel( handler );
+        this.buf.append( "mv.visitTryCatchBlock(" );
+        appendLabel( start );
+        this.buf.append( ", " );
+        appendLabel( end );
+        this.buf.append( ", " );
+        appendLabel( handler );
+        this.buf.append( ", " );
+        appendConstant( type );
+        this.buf.append( ");\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    public void visitLocalVariable(final String name,
+                                   final String desc,
+                                   final String signature,
+                                   final Label start,
+                                   final Label end,
+                                   final int index) {
+        this.buf.setLength( 0 );
+        this.buf.append( "mv.visitLocalVariable(" );
+        appendConstant( name );
+        this.buf.append( ", " );
+        appendConstant( desc );
+        this.buf.append( ", " );
+        appendConstant( signature );
+        this.buf.append( ", " );
+        appendLabel( start );
+        this.buf.append( ", " );
+        appendLabel( end );
+        this.buf.append( ", " ).append( index ).append( ");\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    public void visitLineNumber(final int line,
+                                final Label start) {
+        this.buf.setLength( 0 );
+        this.buf.append( "mv.visitLineNumber(" ).append( line ).append( ", " );
+        appendLabel( start );
+        this.buf.append( ");\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    public void visitMaxs(final int maxStack,
+                          final int maxLocals) {
+        this.buf.setLength( 0 );
+        this.buf.append( "mv.visitMaxs(" ).append( maxStack ).append( ", " ).append( maxLocals ).append( ");\n" );
+        this.text.add( this.buf.toString() );
+    }
+
+    /**
+     * Appends a declaration of the given label to {@link #buf buf}. This
+     * declaration is of the form "Label lXXX = new Label();". Does nothing if
+     * the given label has already been declared.
+     * 
+     * @param l a label.
+     */
+    private void declareLabel(final Label l) {
+        String name = (String) this.labelNames.get( l );
+        if ( name == null ) {
+            name = "l" + this.labelNames.size();
+            this.labelNames.put( l,
+                                 name );
+            this.buf.append( "Label " ).append( name ).append( " = new Label();\n" );
+        }
+    }
+
+    /**
+     * Appends the name of the given label to {@link #buf buf}. The given label
+     * <i>must</i> already have a name. One way to ensure this is to always
+     * call {@link #declareLabel declared} before calling this method.
+     * 
+     * @param l a label.
+     */
+    private void appendLabel(final Label l) {
+        this.buf.append( (String) this.labelNames.get( l ) );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/AbstractVisitor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/AbstractVisitor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/AbstractVisitor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,195 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.util;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.asm.Attribute;
+import org.drools.asm.util.attrs.ASMStackMapAttribute;
+import org.drools.asm.util.attrs.ASMStackMapTableAttribute;
+import org.drools.asm.util.attrs.ASMifiable;
+
+/**
+ * An abstract visitor.
+ * 
+ * @author Eric Bruneton
+ */
+public abstract class AbstractVisitor {
+
+    /**
+     * The names of the Java Virtual Machine opcodes.
+     */
+    public final static String[] OPCODES;
+    /**
+     * Types for <code>operand</code> parameter of the
+     * {@link org.drools.asm.MethodVisitor#visitIntInsn} method when
+     * <code>opcode</code> is <code>NEWARRAY</code>.
+     */
+    public final static String[] TYPES;
+
+    static {
+        String s = "NOP,ACONST_NULL,ICONST_M1,ICONST_0,ICONST_1,ICONST_2," + "ICONST_3,ICONST_4,ICONST_5,LCONST_0,LCONST_1,FCONST_0," + "FCONST_1,FCONST_2,DCONST_0,DCONST_1,BIPUSH,SIPUSH,LDC,,,"
+                   + "ILOAD,LLOAD,FLOAD,DLOAD,ALOAD,,,,,,,,,,,,,,,,,,,,,IALOAD," + "LALOAD,FALOAD,DALOAD,AALOAD,BALOAD,CALOAD,SALOAD,ISTORE," + "LSTORE,FSTORE,DSTORE,ASTORE,,,,,,,,,,,,,,,,,,,,,IASTORE,"
+                   + "LASTORE,FASTORE,DASTORE,AASTORE,BASTORE,CASTORE,SASTORE,POP," + "POP2,DUP,DUP_X1,DUP_X2,DUP2,DUP2_X1,DUP2_X2,SWAP,IADD,LADD," + "FADD,DADD,ISUB,LSUB,FSUB,DSUB,IMUL,LMUL,FMUL,DMUL,IDIV,LDIV,"
+                   + "FDIV,DDIV,IREM,LREM,FREM,DREM,INEG,LNEG,FNEG,DNEG,ISHL,LSHL," + "ISHR,LSHR,IUSHR,LUSHR,IAND,LAND,IOR,LOR,IXOR,LXOR,IINC,I2L," + "I2F,I2D,L2I,L2F,L2D,F2I,F2L,F2D,D2I,D2L,D2F,I2B,I2C,I2S,LCMP,"
+                   + "FCMPL,FCMPG,DCMPL,DCMPG,IFEQ,IFNE,IFLT,IFGE,IFGT,IFLE," + "IF_ICMPEQ,IF_ICMPNE,IF_ICMPLT,IF_ICMPGE,IF_ICMPGT,IF_ICMPLE," + "IF_ACMPEQ,IF_ACMPNE,GOTO,JSR,RET,TABLESWITCH,LOOKUPSWITCH,"
+                   + "IRETURN,LRETURN,FRETURN,DRETURN,ARETURN,RETURN,GETSTATIC," + "PUTSTATIC,GETFIELD,PUTFIELD,INVOKEVIRTUAL,INVOKESPECIAL," + "INVOKESTATIC,INVOKEINTERFACE,,NEW,NEWARRAY,ANEWARRAY,"
+                   + "ARRAYLENGTH,ATHROW,CHECKCAST,INSTANCEOF,MONITORENTER," + "MONITOREXIT,,MULTIANEWARRAY,IFNULL,IFNONNULL,";
+        OPCODES = new String[200];
+        int i = 0;
+        int j = 0;
+        int l;
+        while ( (l = s.indexOf( ',',
+                                j )) > 0 ) {
+            AbstractVisitor.OPCODES[i++] = j + 1 == l ? null : s.substring( j,
+                                                                            l );
+            j = l + 1;
+        }
+
+        s = "T_BOOLEAN,T_CHAR,T_FLOAT,T_DOUBLE,T_BYTE,T_SHORT,T_INT,T_LONG,";
+        TYPES = new String[12];
+        j = 0;
+        i = 4;
+        while ( (l = s.indexOf( ',',
+                                j )) > 0 ) {
+            AbstractVisitor.TYPES[i++] = s.substring( j,
+                                                      l );
+            j = l + 1;
+        }
+    }
+
+    /**
+     * The text to be printed. Since the code of methods is not necessarily
+     * visited in sequential order, one method after the other, but can be
+     * interlaced (some instructions from method one, then some instructions
+     * from method two, then some instructions from method one again...), it is
+     * not possible to print the visited instructions directly to a sequential
+     * stream. A class is therefore printed in a two steps process: a string
+     * tree is constructed during the visit, and printed to a sequential stream
+     * at the end of the visit. This string tree is stored in this field, as a
+     * string list that can contain other string lists, which can themselves
+     * contain other string lists, and so on.
+     */
+    public final List            text;
+
+    /**
+     * A buffer that can be used to create strings.
+     */
+    protected final StringBuffer buf;
+
+    /**
+     * Constructs a new {@link AbstractVisitor}.
+     */
+    protected AbstractVisitor() {
+        this.text = new ArrayList();
+        this.buf = new StringBuffer();
+    }
+
+    /**
+     * Returns the text printed by this visitor.
+     * 
+     * @return the text printed by this visitor.
+     */
+    public List getText() {
+        return this.text;
+    }
+
+    /**
+     * Appends a quoted string to a given buffer.
+     * 
+     * @param buf the buffer where the string must be added.
+     * @param s the string to be added.
+     */
+    public static void appendString(final StringBuffer buf,
+                                    final String s) {
+        buf.append( "\"" );
+        for ( int i = 0; i < s.length(); ++i ) {
+            final char c = s.charAt( i );
+            if ( c == '\n' ) {
+                buf.append( "\\n" );
+            } else if ( c == '\r' ) {
+                buf.append( "\\r" );
+            } else if ( c == '\\' ) {
+                buf.append( "\\\\" );
+            } else if ( c == '"' ) {
+                buf.append( "\\\"" );
+            } else if ( c < 0x20 || c > 0x7f ) {
+                buf.append( "\\u" );
+                if ( c < 0x10 ) {
+                    buf.append( "000" );
+                } else if ( c < 0x100 ) {
+                    buf.append( "00" );
+                } else if ( c < 0x1000 ) {
+                    buf.append( "0" );
+                }
+                buf.append( Integer.toString( c,
+                                              16 ) );
+            } else {
+                buf.append( c );
+            }
+        }
+        buf.append( "\"" );
+    }
+
+    /**
+     * Prints the given string tree.
+     * 
+     * @param pw the writer to be used to print the tree.
+     * @param l a string tree, i.e., a string list that can contain other string
+     *        lists, and so on recursively.
+     */
+    void printList(final PrintWriter pw,
+                   final List l) {
+        for ( int i = 0; i < l.size(); ++i ) {
+            final Object o = l.get( i );
+            if ( o instanceof List ) {
+                printList( pw,
+                           (List) o );
+            } else {
+                pw.print( o.toString() );
+            }
+        }
+    }
+
+    /**
+     * Returns the default {@link ASMifiable} prototypes.
+     * 
+     * @return the default {@link ASMifiable} prototypes.
+     */
+    public static Attribute[] getDefaultAttributes() {
+        try {
+            return new Attribute[]{new ASMStackMapAttribute(), new ASMStackMapTableAttribute()};
+        } catch ( final Exception e ) {
+            return new Attribute[0];
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/CheckAnnotationAdapter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/CheckAnnotationAdapter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/CheckAnnotationAdapter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,123 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.util;
+
+import org.drools.asm.AnnotationVisitor;
+import org.drools.asm.Type;
+
+/**
+ * An {@link AnnotationVisitor} that checks that its methods are properly used.
+ * 
+ * @author Eric Bruneton
+ */
+public class CheckAnnotationAdapter
+    implements
+    AnnotationVisitor {
+
+    private AnnotationVisitor av;
+
+    private boolean           named;
+
+    private boolean           end;
+
+    public CheckAnnotationAdapter(final AnnotationVisitor av) {
+        this( av,
+              true );
+    }
+
+    CheckAnnotationAdapter(final AnnotationVisitor av,
+                           final boolean named) {
+        this.av = av;
+        this.named = named;
+    }
+
+    public void visit(final String name,
+                      final Object value) {
+        checkEnd();
+        checkName( name );
+        if ( !(value instanceof Byte || value instanceof Boolean || value instanceof Character || value instanceof Short || value instanceof Integer || value instanceof Long || value instanceof Float || value instanceof Double
+               || value instanceof String || value instanceof Type || value instanceof byte[] || value instanceof boolean[] || value instanceof char[] || value instanceof short[] || value instanceof int[] || value instanceof long[]
+               || value instanceof float[] || value instanceof double[]) ) {
+            throw new IllegalArgumentException( "Invalid annotation value" );
+        }
+        this.av.visit( name,
+                       value );
+    }
+
+    public void visitEnum(final String name,
+                          final String desc,
+                          final String value) {
+        checkEnd();
+        checkName( name );
+        CheckMethodAdapter.checkDesc( desc,
+                                      false );
+        if ( value == null ) {
+            throw new IllegalArgumentException( "Invalid enum value" );
+        }
+        this.av.visitEnum( name,
+                           desc,
+                           value );
+    }
+
+    public AnnotationVisitor visitAnnotation(final String name,
+                                             final String desc) {
+        checkEnd();
+        checkName( name );
+        CheckMethodAdapter.checkDesc( desc,
+                                      false );
+        return new CheckAnnotationAdapter( this.av.visitAnnotation( name,
+                                                                    desc ) );
+    }
+
+    public AnnotationVisitor visitArray(final String name) {
+        checkEnd();
+        checkName( name );
+        return new CheckAnnotationAdapter( this.av.visitArray( name ),
+                                           false );
+    }
+
+    public void visitEnd() {
+        checkEnd();
+        this.end = true;
+        this.av.visitEnd();
+    }
+
+    private void checkEnd() {
+        if ( this.end ) {
+            throw new IllegalStateException( "Cannot call a visit method after visitEnd has been called" );
+        }
+    }
+
+    private void checkName(final String name) {
+        if ( this.named && name == null ) {
+            throw new IllegalArgumentException( "Annotation value name must not be null" );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/CheckFieldAdapter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/CheckFieldAdapter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/CheckFieldAdapter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,79 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.util;
+
+import org.drools.asm.AnnotationVisitor;
+import org.drools.asm.Attribute;
+import org.drools.asm.FieldVisitor;
+
+/**
+ * A {@link FieldVisitor} that checks that its methods are properly used.
+ */
+public class CheckFieldAdapter
+    implements
+    FieldVisitor {
+
+    private FieldVisitor fv;
+
+    private boolean      end;
+
+    public CheckFieldAdapter(final FieldVisitor fv) {
+        this.fv = fv;
+    }
+
+    public AnnotationVisitor visitAnnotation(final String desc,
+                                             final boolean visible) {
+        checkEnd();
+        CheckMethodAdapter.checkDesc( desc,
+                                      false );
+        return new CheckAnnotationAdapter( this.fv.visitAnnotation( desc,
+                                                                    visible ) );
+    }
+
+    public void visitAttribute(final Attribute attr) {
+        checkEnd();
+        if ( attr == null ) {
+            throw new IllegalArgumentException( "Invalid attribute (must not be null)" );
+        }
+        this.fv.visitAttribute( attr );
+    }
+
+    public void visitEnd() {
+        checkEnd();
+        this.end = true;
+        this.fv.visitEnd();
+    }
+
+    private void checkEnd() {
+        if ( this.end ) {
+            throw new IllegalStateException( "Cannot call a visit method after visitEnd has been called" );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/CheckMethodAdapter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/CheckMethodAdapter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/CheckMethodAdapter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,995 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.util;
+
+import java.util.HashMap;
+
+import org.drools.asm.AnnotationVisitor;
+import org.drools.asm.Attribute;
+import org.drools.asm.Label;
+import org.drools.asm.MethodAdapter;
+import org.drools.asm.MethodVisitor;
+import org.drools.asm.Opcodes;
+import org.drools.asm.Type;
+
+/**
+ * A {@link MethodAdapter} that checks that its methods are properly used. More
+ * precisely this code adapter checks each instruction individually (i.e., each
+ * visit method checks some preconditions based <i>only</i> on its arguments -
+ * such as the fact that the given opcode is correct for a given visit method),
+ * but does <i>not</i> check the <i>sequence</i> of instructions. For example,
+ * in a method whose signature is <tt>void m ()</tt>, the invalid instruction
+ * IRETURN, or the invalid sequence IADD L2I will <i>not</i> be detected by
+ * this code adapter.
+ * 
+ * @author Eric Bruneton
+ */
+public class CheckMethodAdapter extends MethodAdapter {
+
+    /**
+     * <tt>true</tt> if the visitCode method has been called.
+     */
+    private boolean            startCode;
+
+    /**
+     * <tt>true</tt> if the visitMaxs method has been called.
+     */
+    private boolean            endCode;
+
+    /**
+     * <tt>true</tt> if the visitEnd method has been called.
+     */
+    private boolean            endMethod;
+
+    /**
+     * The already visited labels. This map associate Integer values to Label
+     * keys.
+     */
+    private HashMap            labels;
+
+    /**
+     * Code of the visit method to be used for each opcode.
+     */
+    private final static int[] TYPE;
+
+    static {
+        final String s = "BBBBBBBBBBBBBBBBCCIAADDDDDAAAAAAAAAAAAAAAAAAAABBBBBBBBDD" + "DDDAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" + "BBBBBBBBBBBBBBBBBBBJBBBBBBBBBBBBBBBBBBBBHHHHHHHHHHHHHHHHD" + "KLBBBBBBFFFFGGGGAECEBBEEBBAMHHAA";
+        TYPE = new int[s.length()];
+        for ( int i = 0; i < CheckMethodAdapter.TYPE.length; ++i ) {
+            CheckMethodAdapter.TYPE[i] = (s.charAt( i ) - 'A' - 1);
+        }
+    }
+
+    // code to generate the above string
+    // public static void main (String[] args) {
+    // int[] TYPE = new int[] {
+    // 0, //NOP
+    // 0, //ACONST_NULL
+    // 0, //ICONST_M1
+    // 0, //ICONST_0
+    // 0, //ICONST_1
+    // 0, //ICONST_2
+    // 0, //ICONST_3
+    // 0, //ICONST_4
+    // 0, //ICONST_5
+    // 0, //LCONST_0
+    // 0, //LCONST_1
+    // 0, //FCONST_0
+    // 0, //FCONST_1
+    // 0, //FCONST_2
+    // 0, //DCONST_0
+    // 0, //DCONST_1
+    // 1, //BIPUSH
+    // 1, //SIPUSH
+    // 7, //LDC
+    // -1, //LDC_W
+    // -1, //LDC2_W
+    // 2, //ILOAD
+    // 2, //LLOAD
+    // 2, //FLOAD
+    // 2, //DLOAD
+    // 2, //ALOAD
+    // -1, //ILOAD_0
+    // -1, //ILOAD_1
+    // -1, //ILOAD_2
+    // -1, //ILOAD_3
+    // -1, //LLOAD_0
+    // -1, //LLOAD_1
+    // -1, //LLOAD_2
+    // -1, //LLOAD_3
+    // -1, //FLOAD_0
+    // -1, //FLOAD_1
+    // -1, //FLOAD_2
+    // -1, //FLOAD_3
+    // -1, //DLOAD_0
+    // -1, //DLOAD_1
+    // -1, //DLOAD_2
+    // -1, //DLOAD_3
+    // -1, //ALOAD_0
+    // -1, //ALOAD_1
+    // -1, //ALOAD_2
+    // -1, //ALOAD_3
+    // 0, //IALOAD
+    // 0, //LALOAD
+    // 0, //FALOAD
+    // 0, //DALOAD
+    // 0, //AALOAD
+    // 0, //BALOAD
+    // 0, //CALOAD
+    // 0, //SALOAD
+    // 2, //ISTORE
+    // 2, //LSTORE
+    // 2, //FSTORE
+    // 2, //DSTORE
+    // 2, //ASTORE
+    // -1, //ISTORE_0
+    // -1, //ISTORE_1
+    // -1, //ISTORE_2
+    // -1, //ISTORE_3
+    // -1, //LSTORE_0
+    // -1, //LSTORE_1
+    // -1, //LSTORE_2
+    // -1, //LSTORE_3
+    // -1, //FSTORE_0
+    // -1, //FSTORE_1
+    // -1, //FSTORE_2
+    // -1, //FSTORE_3
+    // -1, //DSTORE_0
+    // -1, //DSTORE_1
+    // -1, //DSTORE_2
+    // -1, //DSTORE_3
+    // -1, //ASTORE_0
+    // -1, //ASTORE_1
+    // -1, //ASTORE_2
+    // -1, //ASTORE_3
+    // 0, //IASTORE
+    // 0, //LASTORE
+    // 0, //FASTORE
+    // 0, //DASTORE
+    // 0, //AASTORE
+    // 0, //BASTORE
+    // 0, //CASTORE
+    // 0, //SASTORE
+    // 0, //POP
+    // 0, //POP2
+    // 0, //DUP
+    // 0, //DUP_X1
+    // 0, //DUP_X2
+    // 0, //DUP2
+    // 0, //DUP2_X1
+    // 0, //DUP2_X2
+    // 0, //SWAP
+    // 0, //IADD
+    // 0, //LADD
+    // 0, //FADD
+    // 0, //DADD
+    // 0, //ISUB
+    // 0, //LSUB
+    // 0, //FSUB
+    // 0, //DSUB
+    // 0, //IMUL
+    // 0, //LMUL
+    // 0, //FMUL
+    // 0, //DMUL
+    // 0, //IDIV
+    // 0, //LDIV
+    // 0, //FDIV
+    // 0, //DDIV
+    // 0, //IREM
+    // 0, //LREM
+    // 0, //FREM
+    // 0, //DREM
+    // 0, //INEG
+    // 0, //LNEG
+    // 0, //FNEG
+    // 0, //DNEG
+    // 0, //ISHL
+    // 0, //LSHL
+    // 0, //ISHR
+    // 0, //LSHR
+    // 0, //IUSHR
+    // 0, //LUSHR
+    // 0, //IAND
+    // 0, //LAND
+    // 0, //IOR
+    // 0, //LOR
+    // 0, //IXOR
+    // 0, //LXOR
+    // 8, //IINC
+    // 0, //I2L
+    // 0, //I2F
+    // 0, //I2D
+    // 0, //L2I
+    // 0, //L2F
+    // 0, //L2D
+    // 0, //F2I
+    // 0, //F2L
+    // 0, //F2D
+    // 0, //D2I
+    // 0, //D2L
+    // 0, //D2F
+    // 0, //I2B
+    // 0, //I2C
+    // 0, //I2S
+    // 0, //LCMP
+    // 0, //FCMPL
+    // 0, //FCMPG
+    // 0, //DCMPL
+    // 0, //DCMPG
+    // 6, //IFEQ
+    // 6, //IFNE
+    // 6, //IFLT
+    // 6, //IFGE
+    // 6, //IFGT
+    // 6, //IFLE
+    // 6, //IF_ICMPEQ
+    // 6, //IF_ICMPNE
+    // 6, //IF_ICMPLT
+    // 6, //IF_ICMPGE
+    // 6, //IF_ICMPGT
+    // 6, //IF_ICMPLE
+    // 6, //IF_ACMPEQ
+    // 6, //IF_ACMPNE
+    // 6, //GOTO
+    // 6, //JSR
+    // 2, //RET
+    // 9, //TABLESWITCH
+    // 10, //LOOKUPSWITCH
+    // 0, //IRETURN
+    // 0, //LRETURN
+    // 0, //FRETURN
+    // 0, //DRETURN
+    // 0, //ARETURN
+    // 0, //RETURN
+    // 4, //GETSTATIC
+    // 4, //PUTSTATIC
+    // 4, //GETFIELD
+    // 4, //PUTFIELD
+    // 5, //INVOKEVIRTUAL
+    // 5, //INVOKESPECIAL
+    // 5, //INVOKESTATIC
+    // 5, //INVOKEINTERFACE
+    // -1, //UNUSED
+    // 3, //NEW
+    // 1, //NEWARRAY
+    // 3, //ANEWARRAY
+    // 0, //ARRAYLENGTH
+    // 0, //ATHROW
+    // 3, //CHECKCAST
+    // 3, //INSTANCEOF
+    // 0, //MONITORENTER
+    // 0, //MONITOREXIT
+    // -1, //WIDE
+    // 11, //MULTIANEWARRAY
+    // 6, //IFNULL
+    // 6, //IFNONNULL
+    // -1, //GOTO_W
+    // -1 //JSR_W
+    // };
+    // for (int i = 0; i < TYPE.length; ++i) {
+    // System.out.print((char)(TYPE[i] + 1 + 'A'));
+    // }
+    // System.out.println();
+    // }
+
+    /**
+     * Constructs a new {@link CheckMethodAdapter} object.
+     * 
+     * @param cv the code visitor to which this adapter must delegate calls.
+     */
+    public CheckMethodAdapter(final MethodVisitor cv) {
+        super( cv );
+        this.labels = new HashMap();
+    }
+
+    public AnnotationVisitor visitAnnotation(final String desc,
+                                             final boolean visible) {
+        checkEndMethod();
+        checkDesc( desc,
+                   false );
+        return new CheckAnnotationAdapter( this.mv.visitAnnotation( desc,
+                                                                    visible ) );
+    }
+
+    public AnnotationVisitor visitAnnotationDefault() {
+        checkEndMethod();
+        return new CheckAnnotationAdapter( this.mv.visitAnnotationDefault(),
+                                           false );
+    }
+
+    public AnnotationVisitor visitParameterAnnotation(final int parameter,
+                                                      final String desc,
+                                                      final boolean visible) {
+        checkEndMethod();
+        checkDesc( desc,
+                   false );
+        return new CheckAnnotationAdapter( this.mv.visitParameterAnnotation( parameter,
+                                                                             desc,
+                                                                             visible ) );
+    }
+
+    public void visitAttribute(final Attribute attr) {
+        checkEndMethod();
+        if ( attr == null ) {
+            throw new IllegalArgumentException( "Invalid attribute (must not be null)" );
+        }
+        this.mv.visitAttribute( attr );
+    }
+
+    public void visitCode() {
+        this.startCode = true;
+        this.mv.visitCode();
+    }
+
+    public void visitInsn(final int opcode) {
+        checkStartCode();
+        checkEndCode();
+        checkOpcode( opcode,
+                     0 );
+        this.mv.visitInsn( opcode );
+    }
+
+    public void visitIntInsn(final int opcode,
+                             final int operand) {
+        checkStartCode();
+        checkEndCode();
+        checkOpcode( opcode,
+                     1 );
+        switch ( opcode ) {
+            case Opcodes.BIPUSH :
+                checkSignedByte( operand,
+                                 "Invalid operand" );
+                break;
+            case Opcodes.SIPUSH :
+                checkSignedShort( operand,
+                                  "Invalid operand" );
+                break;
+            // case Constants.NEWARRAY:
+            default :
+                if ( operand < Opcodes.T_BOOLEAN || operand > Opcodes.T_LONG ) {
+                    throw new IllegalArgumentException( "Invalid operand (must be an array type code T_...): " + operand );
+                }
+        }
+        this.mv.visitIntInsn( opcode,
+                              operand );
+    }
+
+    public void visitVarInsn(final int opcode,
+                             final int var) {
+        checkStartCode();
+        checkEndCode();
+        checkOpcode( opcode,
+                     2 );
+        checkUnsignedShort( var,
+                            "Invalid variable index" );
+        this.mv.visitVarInsn( opcode,
+                              var );
+    }
+
+    public void visitTypeInsn(final int opcode,
+                              final String desc) {
+        checkStartCode();
+        checkEndCode();
+        checkOpcode( opcode,
+                     3 );
+        if ( desc != null && desc.length() > 0 && desc.charAt( 0 ) == '[' ) {
+            checkDesc( desc,
+                       false );
+        } else {
+            checkInternalName( desc,
+                               "type" );
+        }
+        if ( opcode == Opcodes.NEW && desc.charAt( 0 ) == '[' ) {
+            throw new IllegalArgumentException( "NEW cannot be used to create arrays: " + desc );
+        }
+        this.mv.visitTypeInsn( opcode,
+                               desc );
+    }
+
+    public void visitFieldInsn(final int opcode,
+                               final String owner,
+                               final String name,
+                               final String desc) {
+        checkStartCode();
+        checkEndCode();
+        checkOpcode( opcode,
+                     4 );
+        checkInternalName( owner,
+                           "owner" );
+        checkIdentifier( name,
+                         "name" );
+        checkDesc( desc,
+                   false );
+        this.mv.visitFieldInsn( opcode,
+                                owner,
+                                name,
+                                desc );
+    }
+
+    public void visitMethodInsn(final int opcode,
+                                final String owner,
+                                final String name,
+                                final String desc) {
+        checkStartCode();
+        checkEndCode();
+        checkOpcode( opcode,
+                     5 );
+        checkMethodIdentifier( name,
+                               "name" );
+        if ( !name.equals( "clone" ) ) {
+            // In JDK1.5, clone method can be called on array class descriptors
+            checkInternalName( owner,
+                               "owner" );
+        }
+        checkMethodDesc( desc );
+        this.mv.visitMethodInsn( opcode,
+                                 owner,
+                                 name,
+                                 desc );
+    }
+
+    public void visitJumpInsn(final int opcode,
+                              final Label label) {
+        checkStartCode();
+        checkEndCode();
+        checkOpcode( opcode,
+                     6 );
+        checkLabel( label,
+                    false,
+                    "label" );
+        this.mv.visitJumpInsn( opcode,
+                               label );
+    }
+
+    public void visitLabel(final Label label) {
+        checkStartCode();
+        checkEndCode();
+        checkLabel( label,
+                    false,
+                    "label" );
+        if ( this.labels.get( label ) != null ) {
+            throw new IllegalArgumentException( "Already visited label" );
+        } else {
+            this.labels.put( label,
+                             new Integer( this.labels.size() ) );
+        }
+        this.mv.visitLabel( label );
+    }
+
+    public void visitLdcInsn(final Object cst) {
+        checkStartCode();
+        checkEndCode();
+        if ( !(cst instanceof Type) ) {
+            checkConstant( cst );
+        }
+        this.mv.visitLdcInsn( cst );
+    }
+
+    public void visitIincInsn(final int var,
+                              final int increment) {
+        checkStartCode();
+        checkEndCode();
+        checkUnsignedShort( var,
+                            "Invalid variable index" );
+        checkSignedShort( increment,
+                          "Invalid increment" );
+        this.mv.visitIincInsn( var,
+                               increment );
+    }
+
+    public void visitTableSwitchInsn(final int min,
+                                     final int max,
+                                     final Label dflt,
+                                     final Label labels[]) {
+        checkStartCode();
+        checkEndCode();
+        if ( max < min ) {
+            throw new IllegalArgumentException( "Max = " + max + " must be greater than or equal to min = " + min );
+        }
+        checkLabel( dflt,
+                    false,
+                    "default label" );
+        if ( labels == null || labels.length != max - min + 1 ) {
+            throw new IllegalArgumentException( "There must be min - min + 1 labels" );
+        }
+        for ( int i = 0; i < labels.length; ++i ) {
+            checkLabel( labels[i],
+                        false,
+                        "label at index " + i );
+        }
+        this.mv.visitTableSwitchInsn( min,
+                                      max,
+                                      dflt,
+                                      labels );
+    }
+
+    public void visitLookupSwitchInsn(final Label dflt,
+                                      final int keys[],
+                                      final Label labels[]) {
+        checkEndCode();
+        checkStartCode();
+        checkLabel( dflt,
+                    false,
+                    "default label" );
+        if ( keys == null || labels == null || keys.length != labels.length ) {
+            throw new IllegalArgumentException( "There must be the same number of keys and labels" );
+        }
+        for ( int i = 0; i < labels.length; ++i ) {
+            checkLabel( labels[i],
+                        false,
+                        "label at index " + i );
+        }
+        this.mv.visitLookupSwitchInsn( dflt,
+                                       keys,
+                                       labels );
+    }
+
+    public void visitMultiANewArrayInsn(final String desc,
+                                        final int dims) {
+        checkStartCode();
+        checkEndCode();
+        checkDesc( desc,
+                   false );
+        if ( desc.charAt( 0 ) != '[' ) {
+            throw new IllegalArgumentException( "Invalid descriptor (must be an array type descriptor): " + desc );
+        }
+        if ( dims < 1 ) {
+            throw new IllegalArgumentException( "Invalid dimensions (must be greater than 0): " + dims );
+        }
+        if ( dims > desc.lastIndexOf( '[' ) + 1 ) {
+            throw new IllegalArgumentException( "Invalid dimensions (must not be greater than dims(desc)): " + dims );
+        }
+        this.mv.visitMultiANewArrayInsn( desc,
+                                         dims );
+    }
+
+    public void visitTryCatchBlock(final Label start,
+                                   final Label end,
+                                   final Label handler,
+                                   final String type) {
+        checkStartCode();
+        checkEndCode();
+        if ( type != null ) {
+            checkInternalName( type,
+                               "type" );
+        }
+        this.mv.visitTryCatchBlock( start,
+                                    end,
+                                    handler,
+                                    type );
+    }
+
+    public void visitLocalVariable(final String name,
+                                   final String desc,
+                                   final String signature,
+                                   final Label start,
+                                   final Label end,
+                                   final int index) {
+        checkStartCode();
+        checkEndCode();
+        checkIdentifier( name,
+                         "name" );
+        checkDesc( desc,
+                   false );
+        checkLabel( start,
+                    true,
+                    "start label" );
+        checkLabel( end,
+                    true,
+                    "end label" );
+        checkUnsignedShort( index,
+                            "Invalid variable index" );
+        final int s = ((Integer) this.labels.get( start )).intValue();
+        final int e = ((Integer) this.labels.get( end )).intValue();
+        if ( e < s ) {
+            throw new IllegalArgumentException( "Invalid start and end labels (end must be greater than start)" );
+        }
+        this.mv.visitLocalVariable( name,
+                                    desc,
+                                    signature,
+                                    start,
+                                    end,
+                                    index );
+    }
+
+    public void visitLineNumber(final int line,
+                                final Label start) {
+        checkStartCode();
+        checkEndCode();
+        checkUnsignedShort( line,
+                            "Invalid line number" );
+        checkLabel( start,
+                    true,
+                    "start label" );
+        this.mv.visitLineNumber( line,
+                                 start );
+    }
+
+    public void visitMaxs(final int maxStack,
+                          final int maxLocals) {
+        checkStartCode();
+        checkEndCode();
+        this.endCode = true;
+        checkUnsignedShort( maxStack,
+                            "Invalid min stack" );
+        checkUnsignedShort( maxLocals,
+                            "Invalid min locals" );
+        this.mv.visitMaxs( maxStack,
+                           maxLocals );
+    }
+
+    public void visitEnd() {
+        checkEndMethod();
+        this.endMethod = true;
+        this.mv.visitEnd();
+    }
+
+    // -------------------------------------------------------------------------
+
+    /**
+     * Checks that the visitCode method has been called.
+     */
+    void checkStartCode() {
+        if ( !this.startCode ) {
+            throw new IllegalStateException( "Cannot visit instructions before visitCode has been called." );
+        }
+    }
+
+    /**
+     * Checks that the visitMaxs method has not been called.
+     */
+    void checkEndCode() {
+        if ( this.endCode ) {
+            throw new IllegalStateException( "Cannot visit instructions after visitMaxs has been called." );
+        }
+    }
+
+    /**
+     * Checks that the visitEnd method has not been called.
+     */
+    void checkEndMethod() {
+        if ( this.endMethod ) {
+            throw new IllegalStateException( "Cannot visit elements after visitEnd has been called." );
+        }
+    }
+
+    /**
+     * Checks that the type of the given opcode is equal to the given type.
+     * 
+     * @param opcode the opcode to be checked.
+     * @param type the expected opcode type.
+     */
+    static void checkOpcode(final int opcode,
+                            final int type) {
+        if ( opcode < 0 || opcode > 199 || CheckMethodAdapter.TYPE[opcode] != type ) {
+            throw new IllegalArgumentException( "Invalid opcode: " + opcode );
+        }
+    }
+
+    /**
+     * Checks that the given value is a signed byte.
+     * 
+     * @param value the value to be checked.
+     * @param msg an message to be used in case of error.
+     */
+    static void checkSignedByte(final int value,
+                                final String msg) {
+        if ( value < Byte.MIN_VALUE || value > Byte.MAX_VALUE ) {
+            throw new IllegalArgumentException( msg + " (must be a signed byte): " + value );
+        }
+    }
+
+    /**
+     * Checks that the given value is a signed short.
+     * 
+     * @param value the value to be checked.
+     * @param msg an message to be used in case of error.
+     */
+    static void checkSignedShort(final int value,
+                                 final String msg) {
+        if ( value < Short.MIN_VALUE || value > Short.MAX_VALUE ) {
+            throw new IllegalArgumentException( msg + " (must be a signed short): " + value );
+        }
+    }
+
+    /**
+     * Checks that the given value is an unsigned short.
+     * 
+     * @param value the value to be checked.
+     * @param msg an message to be used in case of error.
+     */
+    static void checkUnsignedShort(final int value,
+                                   final String msg) {
+        if ( value < 0 || value > 65535 ) {
+            throw new IllegalArgumentException( msg + " (must be an unsigned short): " + value );
+        }
+    }
+
+    /**
+     * Checks that the given value is an {@link Integer}, a{@link Float}, a
+     * {@link Long}, a {@link Double} or a {@link String}.
+     * 
+     * @param cst the value to be checked.
+     */
+    static void checkConstant(final Object cst) {
+        if ( !(cst instanceof Integer) && !(cst instanceof Float) && !(cst instanceof Long) && !(cst instanceof Double) && !(cst instanceof String) ) {
+            throw new IllegalArgumentException( "Invalid constant: " + cst );
+        }
+    }
+
+    /**
+     * Checks that the given string is a valid Java identifier.
+     * 
+     * @param name the string to be checked.
+     * @param msg a message to be used in case of error.
+     */
+    static void checkIdentifier(final String name,
+                                final String msg) {
+        checkIdentifier( name,
+                         0,
+                         -1,
+                         msg );
+    }
+
+    /**
+     * Checks that the given substring is a valid Java identifier.
+     * 
+     * @param name the string to be checked.
+     * @param start index of the first character of the identifier (inclusive).
+     * @param end index of the last character of the identifier (exclusive). -1
+     *        is equivalent to <tt>name.length()</tt> if name is not
+     *        <tt>null</tt>.
+     * @param msg a message to be used in case of error.
+     */
+    static void checkIdentifier(final String name,
+                                final int start,
+                                final int end,
+                                final String msg) {
+        if ( name == null || (end == -1 ? name.length() <= start : end <= start) ) {
+            throw new IllegalArgumentException( "Invalid " + msg + " (must not be null or empty)" );
+        }
+        if ( !Character.isJavaIdentifierStart( name.charAt( start ) ) ) {
+            throw new IllegalArgumentException( "Invalid " + msg + " (must be a valid Java identifier): " + name );
+        }
+        final int max = (end == -1 ? name.length() : end);
+        for ( int i = start + 1; i < max; ++i ) {
+            if ( !Character.isJavaIdentifierPart( name.charAt( i ) ) ) {
+                throw new IllegalArgumentException( "Invalid " + msg + " (must be a valid Java identifier): " + name );
+            }
+        }
+    }
+
+    /**
+     * Checks that the given string is a valid Java identifier or is equal to
+     * '&lt;init&gt;' or '&lt;clinit&gt;'.
+     * 
+     * @param name the string to be checked.
+     * @param msg a message to be used in case of error.
+     */
+    static void checkMethodIdentifier(final String name,
+                                      final String msg) {
+        if ( name == null || name.length() == 0 ) {
+            throw new IllegalArgumentException( "Invalid " + msg + " (must not be null or empty)" );
+        }
+        if ( name.equals( "<init>" ) || name.equals( "<clinit>" ) ) {
+            return;
+        }
+        if ( !Character.isJavaIdentifierStart( name.charAt( 0 ) ) ) {
+            throw new IllegalArgumentException( "Invalid " + msg + " (must be a '<init>', '<clinit>' or a valid Java identifier): " + name );
+        }
+        for ( int i = 1; i < name.length(); ++i ) {
+            if ( !Character.isJavaIdentifierPart( name.charAt( i ) ) ) {
+                throw new IllegalArgumentException( "Invalid " + msg + " (must be '<init>' or '<clinit>' or a valid Java identifier): " + name );
+            }
+        }
+    }
+
+    /**
+     * Checks that the given string is a valid internal class name.
+     * 
+     * @param name the string to be checked.
+     * @param msg a message to be used in case of error.
+     */
+    static void checkInternalName(final String name,
+                                  final String msg) {
+        checkInternalName( name,
+                           0,
+                           -1,
+                           msg );
+    }
+
+    /**
+     * Checks that the given substring is a valid internal class name.
+     * 
+     * @param name the string to be checked.
+     * @param start index of the first character of the identifier (inclusive).
+     * @param end index of the last character of the identifier (exclusive). -1
+     *        is equivalent to <tt>name.length()</tt> if name is not
+     *        <tt>null</tt>.
+     * @param msg a message to be used in case of error.
+     */
+    static void checkInternalName(final String name,
+                                  final int start,
+                                  final int end,
+                                  final String msg) {
+        if ( name == null || name.length() == 0 ) {
+            throw new IllegalArgumentException( "Invalid " + msg + " (must not be null or empty)" );
+        }
+        final int max = (end == -1 ? name.length() : end);
+        try {
+            int begin = start;
+            int slash;
+            do {
+                slash = name.indexOf( '/',
+                                      begin + 1 );
+                if ( slash == -1 || slash > max ) {
+                    slash = max;
+                }
+                checkIdentifier( name,
+                                 begin,
+                                 slash,
+                                 null );
+                begin = slash + 1;
+            } while ( slash != max );
+        } catch ( final IllegalArgumentException _ ) {
+            throw new IllegalArgumentException( "Invalid " + msg + " (must be a fully qualified class name in internal form): " + name );
+        }
+    }
+
+    /**
+     * Checks that the given string is a valid type descriptor.
+     * 
+     * @param desc the string to be checked.
+     * @param canBeVoid <tt>true</tt> if <tt>V</tt> can be considered valid.
+     */
+    static void checkDesc(final String desc,
+                          final boolean canBeVoid) {
+        final int end = checkDesc( desc,
+                                   0,
+                                   canBeVoid );
+        if ( end != desc.length() ) {
+            throw new IllegalArgumentException( "Invalid descriptor: " + desc );
+        }
+    }
+
+    /**
+     * Checks that a the given substring is a valid type descriptor.
+     * 
+     * @param desc the string to be checked.
+     * @param start index of the first character of the identifier (inclusive).
+     * @param canBeVoid <tt>true</tt> if <tt>V</tt> can be considered valid.
+     * @return the index of the last character of the type decriptor, plus one.
+     */
+    static int checkDesc(final String desc,
+                         final int start,
+                         final boolean canBeVoid) {
+        if ( desc == null || start >= desc.length() ) {
+            throw new IllegalArgumentException( "Invalid type descriptor (must not be null or empty)" );
+        }
+        int index;
+        switch ( desc.charAt( start ) ) {
+            case 'V' :
+                if ( canBeVoid ) {
+                    return start + 1;
+                } else {
+                    throw new IllegalArgumentException( "Invalid descriptor: " + desc );
+                }
+            case 'Z' :
+            case 'C' :
+            case 'B' :
+            case 'S' :
+            case 'I' :
+            case 'F' :
+            case 'J' :
+            case 'D' :
+                return start + 1;
+            case '[' :
+                index = start + 1;
+                while ( index < desc.length() && desc.charAt( index ) == '[' ) {
+                    ++index;
+                }
+                if ( index < desc.length() ) {
+                    return checkDesc( desc,
+                                      index,
+                                      false );
+                } else {
+                    throw new IllegalArgumentException( "Invalid descriptor: " + desc );
+                }
+            case 'L' :
+                index = desc.indexOf( ';',
+                                      start );
+                if ( index == -1 || index - start < 2 ) {
+                    throw new IllegalArgumentException( "Invalid descriptor: " + desc );
+                }
+                try {
+                    checkInternalName( desc,
+                                       start + 1,
+                                       index,
+                                       null );
+                } catch ( final IllegalArgumentException _ ) {
+                    throw new IllegalArgumentException( "Invalid descriptor: " + desc );
+                }
+                return index + 1;
+            default :
+                throw new IllegalArgumentException( "Invalid descriptor: " + desc );
+        }
+    }
+
+    /**
+     * Checks that the given string is a valid method descriptor.
+     * 
+     * @param desc the string to be checked.
+     */
+    static void checkMethodDesc(final String desc) {
+        if ( desc == null || desc.length() == 0 ) {
+            throw new IllegalArgumentException( "Invalid method descriptor (must not be null or empty)" );
+        }
+        if ( desc.charAt( 0 ) != '(' || desc.length() < 3 ) {
+            throw new IllegalArgumentException( "Invalid descriptor: " + desc );
+        }
+        int start = 1;
+        if ( desc.charAt( start ) != ')' ) {
+            do {
+                if ( desc.charAt( start ) == 'V' ) {
+                    throw new IllegalArgumentException( "Invalid descriptor: " + desc );
+                }
+                start = checkDesc( desc,
+                                   start,
+                                   false );
+            } while ( start < desc.length() && desc.charAt( start ) != ')' );
+        }
+        start = checkDesc( desc,
+                           start + 1,
+                           true );
+        if ( start != desc.length() ) {
+            throw new IllegalArgumentException( "Invalid descriptor: " + desc );
+        }
+    }
+
+    /**
+     * Checks that the given label is not null. This method can also check that
+     * the label has been visited.
+     * 
+     * @param label the label to be checked.
+     * @param checkVisited <tt>true</tt> to check that the label has been
+     *        visited.
+     * @param msg a message to be used in case of error.
+     */
+    void checkLabel(final Label label,
+                    final boolean checkVisited,
+                    final String msg) {
+        if ( label == null ) {
+            throw new IllegalArgumentException( "Invalid " + msg + " (must not be null)" );
+        }
+        if ( checkVisited && this.labels.get( label ) == null ) {
+            throw new IllegalArgumentException( "Invalid " + msg + " (must be visited first)" );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceAbstractVisitor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceAbstractVisitor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceAbstractVisitor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,180 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.util;
+
+import org.drools.asm.AnnotationVisitor;
+import org.drools.asm.Attribute;
+import org.drools.asm.util.attrs.Traceable;
+
+/**
+ * An abstract trace visitor.
+ * 
+ * @author Eric Bruneton
+ */
+public abstract class TraceAbstractVisitor extends AbstractVisitor {
+
+    /**
+     * Constant used in {@link #appendDescriptor appendDescriptor} for internal
+     * type names in bytecode notation.
+     */
+    public final static int INTERNAL_NAME          = 0;
+
+    /**
+     * Constant used in {@link #appendDescriptor appendDescriptor} for field
+     * descriptors, formatted in bytecode notation
+     */
+    public final static int FIELD_DESCRIPTOR       = 1;
+
+    /**
+     * Constant used in {@link #appendDescriptor appendDescriptor} for field
+     * signatures, formatted in bytecode notation
+     */
+    public final static int FIELD_SIGNATURE        = 2;
+
+    /**
+     * Constant used in {@link #appendDescriptor appendDescriptor} for method
+     * descriptors, formatted in bytecode notation
+     */
+    public final static int METHOD_DESCRIPTOR      = 3;
+
+    /**
+     * Constant used in {@link #appendDescriptor appendDescriptor} for method
+     * signatures, formatted in bytecode notation
+     */
+    public final static int METHOD_SIGNATURE       = 4;
+
+    /**
+     * Constant used in {@link #appendDescriptor appendDescriptor} for class
+     * signatures, formatted in bytecode notation
+     */
+    public final static int CLASS_SIGNATURE        = 5;
+
+    /**
+     * Constant used in {@link #appendDescriptor appendDescriptor} for field or
+     * method return value signatures, formatted in default Java notation
+     * (non-bytecode)
+     */
+    public final static int TYPE_DECLARATION       = 6;
+
+    /**
+     * Constant used in {@link #appendDescriptor appendDescriptor} for class
+     * signatures, formatted in default Java notation (non-bytecode)
+     */
+    public final static int CLASS_DECLARATION      = 7;
+
+    /**
+     * Constant used in {@link #appendDescriptor appendDescriptor} for method
+     * parameter signatures, formatted in default Java notation (non-bytecode)
+     */
+    public final static int PARAMETERS_DECLARATION = 8;
+
+    /**
+     * Tab for class members.
+     */
+    protected String        tab                    = "  ";
+
+    /**
+     * Prints a disassembled view of the given annotation.
+     * 
+     * @param desc the class descriptor of the annotation class.
+     * @param visible <tt>true</tt> if the annotation is visible at runtime.
+     * @return a visitor to visit the annotation values.
+     */
+    public AnnotationVisitor visitAnnotation(final String desc,
+                                             final boolean visible) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab ).append( '@' );
+        appendDescriptor( TraceAbstractVisitor.FIELD_DESCRIPTOR,
+                          desc );
+        this.buf.append( '(' );
+        this.text.add( this.buf.toString() );
+        final TraceAnnotationVisitor tav = createTraceAnnotationVisitor();
+        this.text.add( tav.getText() );
+        this.text.add( visible ? ")\n" : ") // invisible\n" );
+        return tav;
+    }
+
+    /**
+     * Prints a disassembled view of the given attribute.
+     * 
+     * @param attr an attribute.
+     */
+    public void visitAttribute(final Attribute attr) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab ).append( "ATTRIBUTE " );
+        appendDescriptor( -1,
+                          attr.type );
+
+        if ( attr instanceof Traceable ) {
+            ((Traceable) attr).trace( this.buf,
+                                      null );
+        } else {
+            this.buf.append( " : " ).append( attr.toString() ).append( "\n" );
+        }
+
+        this.text.add( this.buf.toString() );
+    }
+
+    /**
+     * Does nothing.
+     */
+    public void visitEnd() {
+        // does nothing
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods
+    // ------------------------------------------------------------------------
+
+    protected TraceAnnotationVisitor createTraceAnnotationVisitor() {
+        return new TraceAnnotationVisitor();
+    }
+
+    /**
+     * Appends an internal name, a type descriptor or a type signature to
+     * {@link #buf buf}.
+     * 
+     * @param type indicates if desc is an internal name, a field descriptor, a
+     *        method descriptor, a class signature, ...
+     * @param desc an internal name, type descriptor, or type signature. May be
+     *        <tt>null</tt>.
+     */
+    protected void appendDescriptor(final int type,
+                                    final String desc) {
+        if ( type == TraceAbstractVisitor.CLASS_SIGNATURE || type == TraceAbstractVisitor.FIELD_SIGNATURE || type == TraceAbstractVisitor.METHOD_SIGNATURE ) {
+            if ( desc != null ) {
+                this.buf.append( "// signature " ).append( desc ).append( '\n' );
+            }
+        } else {
+            this.buf.append( desc );
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceAnnotationVisitor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceAnnotationVisitor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceAnnotationVisitor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,276 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.util;
+
+import org.drools.asm.AnnotationVisitor;
+import org.drools.asm.Type;
+
+/**
+ * An {@link AnnotationVisitor} that prints a disassembled view of the
+ * annotations it visits.
+ * 
+ * @author Eric Bruneton
+ */
+public class TraceAnnotationVisitor extends TraceAbstractVisitor
+    implements
+    AnnotationVisitor {
+
+    /**
+     * The {@link AnnotationVisitor} to which this visitor delegates calls. May
+     * be <tt>null</tt>.
+     */
+    protected AnnotationVisitor av;
+
+    private int                 valueNumber = 0;
+
+    /**
+     * Constructs a new {@link TraceAnnotationVisitor}.
+     */
+    public TraceAnnotationVisitor() {
+        // ignore
+    }
+
+    // ------------------------------------------------------------------------
+    // Implementation of the AnnotationVisitor interface
+    // ------------------------------------------------------------------------
+
+    public void visit(final String name,
+                      final Object value) {
+        this.buf.setLength( 0 );
+        appendComa( this.valueNumber++ );
+
+        if ( name != null ) {
+            this.buf.append( name ).append( '=' );
+        }
+
+        if ( value instanceof String ) {
+            visitString( (String) value );
+        } else if ( value instanceof Type ) {
+            visitType( (Type) value );
+        } else if ( value instanceof Byte ) {
+            visitByte( ((Byte) value).byteValue() );
+        } else if ( value instanceof Boolean ) {
+            visitBoolean( ((Boolean) value).booleanValue() );
+        } else if ( value instanceof Short ) {
+            visitShort( ((Short) value).shortValue() );
+        } else if ( value instanceof Character ) {
+            visitChar( ((Character) value).charValue() );
+        } else if ( value instanceof Integer ) {
+            visitInt( ((Integer) value).intValue() );
+        } else if ( value instanceof Float ) {
+            visitFloat( ((Float) value).floatValue() );
+        } else if ( value instanceof Long ) {
+            visitLong( ((Long) value).longValue() );
+        } else if ( value instanceof Double ) {
+            visitDouble( ((Double) value).doubleValue() );
+        } else if ( value.getClass().isArray() ) {
+            this.buf.append( '{' );
+            if ( value instanceof byte[] ) {
+                final byte[] v = (byte[]) value;
+                for ( int i = 0; i < v.length; i++ ) {
+                    appendComa( i );
+                    visitByte( v[i] );
+                }
+            } else if ( value instanceof boolean[] ) {
+                final boolean[] v = (boolean[]) value;
+                for ( int i = 0; i < v.length; i++ ) {
+                    appendComa( i );
+                    visitBoolean( v[i] );
+                }
+            } else if ( value instanceof short[] ) {
+                final short[] v = (short[]) value;
+                for ( int i = 0; i < v.length; i++ ) {
+                    appendComa( i );
+                    visitShort( v[i] );
+                }
+            } else if ( value instanceof char[] ) {
+                final char[] v = (char[]) value;
+                for ( int i = 0; i < v.length; i++ ) {
+                    appendComa( i );
+                    visitChar( v[i] );
+                }
+            } else if ( value instanceof int[] ) {
+                final int[] v = (int[]) value;
+                for ( int i = 0; i < v.length; i++ ) {
+                    appendComa( i );
+                    visitInt( v[i] );
+                }
+            } else if ( value instanceof long[] ) {
+                final long[] v = (long[]) value;
+                for ( int i = 0; i < v.length; i++ ) {
+                    appendComa( i );
+                    visitLong( v[i] );
+                }
+            } else if ( value instanceof float[] ) {
+                final float[] v = (float[]) value;
+                for ( int i = 0; i < v.length; i++ ) {
+                    appendComa( i );
+                    visitFloat( v[i] );
+                }
+            } else if ( value instanceof double[] ) {
+                final double[] v = (double[]) value;
+                for ( int i = 0; i < v.length; i++ ) {
+                    appendComa( i );
+                    visitDouble( v[i] );
+                }
+            }
+            this.buf.append( '}' );
+        } else {
+            this.buf.append( value );
+        }
+
+        this.text.add( this.buf.toString() );
+
+        if ( this.av != null ) {
+            this.av.visit( name,
+                           value );
+        }
+    }
+
+    private void visitInt(final int value) {
+        this.buf.append( value );
+    }
+
+    private void visitLong(final long value) {
+        this.buf.append( value ).append( 'L' );
+    }
+
+    private void visitFloat(final float value) {
+        this.buf.append( value ).append( 'F' );
+    }
+
+    private void visitDouble(final double value) {
+        this.buf.append( value ).append( 'D' );
+    }
+
+    private void visitChar(final char value) {
+        this.buf.append( "(char)" ).append( (int) value );
+    }
+
+    private void visitShort(final short value) {
+        this.buf.append( "(short)" ).append( value );
+    }
+
+    private void visitByte(final byte value) {
+        this.buf.append( "(byte)" ).append( value );
+    }
+
+    private void visitBoolean(final boolean value) {
+        this.buf.append( value );
+    }
+
+    private void visitString(final String value) {
+        appendString( this.buf,
+                      value );
+    }
+
+    private void visitType(final Type value) {
+        this.buf.append( value.getClassName() ).append( ".class" );
+    }
+
+    public void visitEnum(final String name,
+                          final String desc,
+                          final String value) {
+        this.buf.setLength( 0 );
+        appendComa( this.valueNumber++ );
+        if ( name != null ) {
+            this.buf.append( name ).append( '=' );
+        }
+        appendDescriptor( TraceAbstractVisitor.FIELD_DESCRIPTOR,
+                          desc );
+        this.buf.append( '.' ).append( value );
+        this.text.add( this.buf.toString() );
+
+        if ( this.av != null ) {
+            this.av.visitEnum( name,
+                               desc,
+                               value );
+        }
+    }
+
+    public AnnotationVisitor visitAnnotation(final String name,
+                                             final String desc) {
+        this.buf.setLength( 0 );
+        appendComa( this.valueNumber++ );
+        if ( name != null ) {
+            this.buf.append( name ).append( '=' );
+        }
+        this.buf.append( '@' );
+        appendDescriptor( TraceAbstractVisitor.FIELD_DESCRIPTOR,
+                          desc );
+        this.buf.append( '(' );
+        this.text.add( this.buf.toString() );
+        final TraceAnnotationVisitor tav = createTraceAnnotationVisitor();
+        this.text.add( tav.getText() );
+        this.text.add( ")" );
+        if ( this.av != null ) {
+            tav.av = this.av.visitAnnotation( name,
+                                              desc );
+        }
+        return tav;
+    }
+
+    public AnnotationVisitor visitArray(final String name) {
+        this.buf.setLength( 0 );
+        appendComa( this.valueNumber++ );
+        if ( name != null ) {
+            this.buf.append( name ).append( '=' );
+        }
+        this.buf.append( '{' );
+        this.text.add( this.buf.toString() );
+        final TraceAnnotationVisitor tav = createTraceAnnotationVisitor();
+        this.text.add( tav.getText() );
+        this.text.add( "}" );
+        if ( this.av != null ) {
+            tav.av = this.av.visitArray( name );
+        }
+        return tav;
+    }
+
+    public void visitEnd() {
+        if ( this.av != null ) {
+            this.av.visitEnd();
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods
+    // ------------------------------------------------------------------------
+
+    protected TraceAnnotationVisitor createTraceAnnotationVisitor() {
+        return new TraceAnnotationVisitor();
+    }
+
+    private void appendComa(final int i) {
+        if ( i != 0 ) {
+            this.buf.append( ", " );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceClassVisitor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceClassVisitor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceClassVisitor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,533 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.util;
+
+import java.io.FileInputStream;
+import java.io.PrintWriter;
+
+import org.drools.asm.AnnotationVisitor;
+import org.drools.asm.Attribute;
+import org.drools.asm.ClassReader;
+import org.drools.asm.ClassVisitor;
+import org.drools.asm.FieldVisitor;
+import org.drools.asm.MethodVisitor;
+import org.drools.asm.Opcodes;
+import org.drools.asm.signature.SignatureReader;
+
+/**
+ * A {@link ClassVisitor} that prints a disassembled view of the classes it
+ * visits. This class visitor can be used alone (see the {@link #main main}
+ * method) to disassemble a class. It can also be used in the middle of class
+ * visitor chain to trace the class that is visited at a given point in this
+ * chain. This may be uselful for debugging purposes. <p> The trace printed when
+ * visiting the <tt>Hello</tt> class is the following: <p> <blockquote>
+ * 
+ * <pre>
+ * // class version 49.0 (49)
+ * // access flags 33
+ * public class Hello {
+ *
+ *  // compiled from: Hello.java
+ *
+ *   // access flags 1
+ *   public &lt;init&gt; ()V
+ *     ALOAD 0
+ *     INVOKESPECIAL java/lang/Object &lt;init&gt; ()V
+ *     RETURN
+ *     MAXSTACK = 1
+ *     MAXLOCALS = 1
+ *
+ *   // access flags 9
+ *   public static main ([Ljava/lang/String;)V
+ *     GETSTATIC java/lang/System out Ljava/io/PrintStream;
+ *     LDC &quot;hello&quot;
+ *     INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V
+ *     RETURN
+ *     MAXSTACK = 2
+ *     MAXLOCALS = 1
+ * }
+ * </pre>
+ * 
+ * </blockquote> where <tt>Hello</tt> is defined by: <p> <blockquote>
+ * 
+ * <pre>
+ * public class Hello {
+ *
+ *     public static void main(String[] args) {
+ *         System.out.println(&quot;hello&quot;);
+ *     }
+ * }
+ * </pre>
+ * 
+ * </blockquote>
+ * 
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class TraceClassVisitor extends TraceAbstractVisitor
+    implements
+    ClassVisitor {
+
+    /**
+     * The {@link ClassVisitor} to which this visitor delegates calls. May be
+     * <tt>null</tt>.
+     */
+    protected final ClassVisitor cv;
+
+    /**
+     * The print writer to be used to print the class.
+     */
+    protected final PrintWriter  pw;
+
+    /**
+     * Prints a disassembled view of the given class to the standard output. <p>
+     * Usage: TraceClassVisitor [-debug] &lt;fully qualified class name or class
+     * file name &gt;
+     * 
+     * @param args the command line arguments.
+     * 
+     * @throws Exception if the class cannot be found, or if an IO exception
+     *         occurs.
+     */
+    public static void main(final String[] args) throws Exception {
+        int i = 0;
+        boolean skipDebug = true;
+
+        boolean ok = true;
+        if ( args.length < 1 || args.length > 2 ) {
+            ok = false;
+        }
+        if ( ok && args[0].equals( "-debug" ) ) {
+            i = 1;
+            skipDebug = false;
+            if ( args.length != 2 ) {
+                ok = false;
+            }
+        }
+        if ( !ok ) {
+            System.err.println( "Prints a disassembled view of the given class." );
+            System.err.println( "Usage: TraceClassVisitor [-debug] " + "<fully qualified class name or class file name>" );
+            return;
+        }
+        ClassReader cr;
+        if ( args[i].endsWith( ".class" ) || args[i].indexOf( '\\' ) > -1 || args[i].indexOf( '/' ) > -1 ) {
+            cr = new ClassReader( new FileInputStream( args[i] ) );
+        } else {
+            cr = new ClassReader( args[i] );
+        }
+        cr.accept( new TraceClassVisitor( new PrintWriter( System.out ) ),
+                   getDefaultAttributes(),
+                   skipDebug );
+    }
+
+    /**
+     * Constructs a new {@link TraceClassVisitor}.
+     * 
+     * @param pw the print writer to be used to print the class.
+     */
+    public TraceClassVisitor(final PrintWriter pw) {
+        this( null,
+              pw );
+    }
+
+    /**
+     * Constructs a new {@link TraceClassVisitor}.
+     * 
+     * @param cv the {@link ClassVisitor} to which this visitor delegates calls.
+     *        May be <tt>null</tt>.
+     * @param pw the print writer to be used to print the class.
+     */
+    public TraceClassVisitor(final ClassVisitor cv,
+                             final PrintWriter pw) {
+        this.cv = cv;
+        this.pw = pw;
+    }
+
+    // ------------------------------------------------------------------------
+    // Implementation of the ClassVisitor interface
+    // ------------------------------------------------------------------------
+
+    public void visit(final int version,
+                      final int access,
+                      final String name,
+                      final String signature,
+                      final String superName,
+                      final String[] interfaces) {
+        final int major = version & 0xFFFF;
+        final int minor = version >>> 16;
+        this.buf.setLength( 0 );
+        this.buf.append( "// class version " ).append( major ).append( '.' ).append( minor ).append( " (" ).append( version ).append( ")\n" );
+        if ( (access & Opcodes.ACC_DEPRECATED) != 0 ) {
+            this.buf.append( "// DEPRECATED\n" );
+        }
+        this.buf.append( "// access flags " ).append( access ).append( '\n' );
+
+        appendDescriptor( TraceAbstractVisitor.CLASS_SIGNATURE,
+                          signature );
+        if ( signature != null ) {
+            final TraceSignatureVisitor sv = new TraceSignatureVisitor( access );
+            final SignatureReader r = new SignatureReader( signature );
+            r.accept( sv );
+            this.buf.append( "// declaration: " ).append( name ).append( sv.getDeclaration() ).append( '\n' );
+        }
+
+        appendAccess( access & ~Opcodes.ACC_SUPER );
+        if ( (access & Opcodes.ACC_ANNOTATION) != 0 ) {
+            this.buf.append( "@interface " );
+        } else if ( (access & Opcodes.ACC_INTERFACE) != 0 ) {
+            this.buf.append( "interface " );
+        } else if ( (access & Opcodes.ACC_ENUM) != 0 ) {
+            this.buf.append( "enum " );
+        } else {
+            this.buf.append( "class " );
+        }
+        appendDescriptor( TraceAbstractVisitor.INTERNAL_NAME,
+                          name );
+
+        if ( superName != null && !superName.equals( "java/lang/Object" ) ) {
+            this.buf.append( " extends " );
+            appendDescriptor( TraceAbstractVisitor.INTERNAL_NAME,
+                              superName );
+            this.buf.append( ' ' );
+        }
+        if ( interfaces != null && interfaces.length > 0 ) {
+            this.buf.append( " implements " );
+            for ( int i = 0; i < interfaces.length; ++i ) {
+                appendDescriptor( TraceAbstractVisitor.INTERNAL_NAME,
+                                  interfaces[i] );
+                this.buf.append( ' ' );
+            }
+        }
+        this.buf.append( " {\n\n" );
+
+        this.text.add( this.buf.toString() );
+
+        if ( this.cv != null ) {
+            this.cv.visit( version,
+                           access,
+                           name,
+                           signature,
+                           superName,
+                           interfaces );
+        }
+    }
+
+    public void visitSource(final String file,
+                            final String debug) {
+        this.buf.setLength( 0 );
+        if ( file != null ) {
+            this.buf.append( this.tab ).append( "// compiled from: " ).append( file ).append( '\n' );
+        }
+        if ( debug != null ) {
+            this.buf.append( this.tab ).append( "// debug info: " ).append( debug ).append( '\n' );
+        }
+        if ( this.buf.length() > 0 ) {
+            this.text.add( this.buf.toString() );
+        }
+
+        if ( this.cv != null ) {
+            this.cv.visitSource( file,
+                                 debug );
+        }
+    }
+
+    public void visitOuterClass(final String owner,
+                                final String name,
+                                final String desc) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab ).append( "OUTERCLASS " );
+        appendDescriptor( TraceAbstractVisitor.INTERNAL_NAME,
+                          owner );
+        // if enclosing name is null, so why should we show this info?
+        if ( name != null ) {
+            this.buf.append( ' ' ).append( name ).append( ' ' );
+        } else {
+            this.buf.append( ' ' );
+        }
+        appendDescriptor( TraceAbstractVisitor.METHOD_DESCRIPTOR,
+                          desc );
+        this.buf.append( '\n' );
+        this.text.add( this.buf.toString() );
+
+        if ( this.cv != null ) {
+            this.cv.visitOuterClass( owner,
+                                     name,
+                                     desc );
+        }
+    }
+
+    public AnnotationVisitor visitAnnotation(final String desc,
+                                             final boolean visible) {
+        this.text.add( "\n" );
+        final AnnotationVisitor tav = super.visitAnnotation( desc,
+                                                             visible );
+        if ( this.cv != null ) {
+            ((TraceAnnotationVisitor) tav).av = this.cv.visitAnnotation( desc,
+                                                                         visible );
+        }
+        return tav;
+    }
+
+    public void visitAttribute(final Attribute attr) {
+        this.text.add( "\n" );
+        super.visitAttribute( attr );
+
+        if ( this.cv != null ) {
+            this.cv.visitAttribute( attr );
+        }
+    }
+
+    public void visitInnerClass(final String name,
+                                final String outerName,
+                                final String innerName,
+                                final int access) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab ).append( "// access flags " ).append( access & ~Opcodes.ACC_SUPER ).append( '\n' );
+        this.buf.append( this.tab );
+        appendAccess( access );
+        this.buf.append( "INNERCLASS " );
+        if ( (access & Opcodes.ACC_ENUM) != 0 ) {
+            this.buf.append( "enum " );
+        }
+        appendDescriptor( TraceAbstractVisitor.INTERNAL_NAME,
+                          name );
+        this.buf.append( ' ' );
+        appendDescriptor( TraceAbstractVisitor.INTERNAL_NAME,
+                          outerName );
+        this.buf.append( ' ' );
+        appendDescriptor( TraceAbstractVisitor.INTERNAL_NAME,
+                          innerName );
+        this.buf.append( '\n' );
+        this.text.add( this.buf.toString() );
+
+        if ( this.cv != null ) {
+            this.cv.visitInnerClass( name,
+                                     outerName,
+                                     innerName,
+                                     access );
+        }
+    }
+
+    public FieldVisitor visitField(final int access,
+                                   final String name,
+                                   final String desc,
+                                   final String signature,
+                                   final Object value) {
+        this.buf.setLength( 0 );
+        this.buf.append( '\n' );
+        if ( (access & Opcodes.ACC_DEPRECATED) != 0 ) {
+            this.buf.append( this.tab ).append( "// DEPRECATED\n" );
+        }
+        this.buf.append( this.tab ).append( "// access flags " ).append( access ).append( '\n' );
+        if ( signature != null ) {
+            this.buf.append( this.tab );
+            appendDescriptor( TraceAbstractVisitor.FIELD_SIGNATURE,
+                              signature );
+
+            final TraceSignatureVisitor sv = new TraceSignatureVisitor( 0 );
+            final SignatureReader r = new SignatureReader( signature );
+            r.acceptType( sv );
+            this.buf.append( this.tab ).append( "// declaration: " ).append( sv.getDeclaration() ).append( '\n' );
+        }
+
+        this.buf.append( this.tab );
+        appendAccess( access );
+        if ( (access & Opcodes.ACC_ENUM) != 0 ) {
+            this.buf.append( "enum " );
+        }
+
+        appendDescriptor( TraceAbstractVisitor.FIELD_DESCRIPTOR,
+                          desc );
+        this.buf.append( ' ' ).append( name );
+        if ( value != null ) {
+            this.buf.append( " = " );
+            if ( value instanceof String ) {
+                this.buf.append( "\"" ).append( value ).append( "\"" );
+            } else {
+                this.buf.append( value );
+            }
+        }
+
+        this.buf.append( '\n' );
+        this.text.add( this.buf.toString() );
+
+        final TraceFieldVisitor tav = createTraceFieldVisitor();
+        this.text.add( tav.getText() );
+
+        if ( this.cv != null ) {
+            tav.fv = this.cv.visitField( access,
+                                         name,
+                                         desc,
+                                         signature,
+                                         value );
+        }
+
+        return tav;
+    }
+
+    public MethodVisitor visitMethod(final int access,
+                                     final String name,
+                                     final String desc,
+                                     final String signature,
+                                     final String[] exceptions) {
+        this.buf.setLength( 0 );
+        this.buf.append( '\n' );
+        if ( (access & Opcodes.ACC_DEPRECATED) != 0 ) {
+            this.buf.append( this.tab ).append( "// DEPRECATED\n" );
+        }
+        this.buf.append( this.tab ).append( "// access flags " ).append( access ).append( '\n' );
+        this.buf.append( this.tab );
+        appendDescriptor( TraceAbstractVisitor.METHOD_SIGNATURE,
+                          signature );
+
+        if ( signature != null ) {
+            final TraceSignatureVisitor v = new TraceSignatureVisitor( 0 );
+            final SignatureReader r = new SignatureReader( signature );
+            r.accept( v );
+            final String genericDecl = v.getDeclaration();
+            final String genericReturn = v.getReturnType();
+            final String genericExceptions = v.getExceptions();
+
+            this.buf.append( this.tab ).append( "// declaration: " ).append( genericReturn ).append( ' ' ).append( name ).append( genericDecl );
+            if ( genericExceptions != null ) {
+                this.buf.append( " throws " ).append( genericExceptions );
+            }
+            this.buf.append( '\n' );
+        }
+
+        appendAccess( access );
+        if ( (access & Opcodes.ACC_NATIVE) != 0 ) {
+            this.buf.append( "native " );
+        }
+        if ( (access & Opcodes.ACC_VARARGS) != 0 ) {
+            this.buf.append( "varargs " );
+        }
+        if ( (access & Opcodes.ACC_BRIDGE) != 0 ) {
+            this.buf.append( "bridge " );
+        }
+
+        this.buf.append( name );
+        appendDescriptor( TraceAbstractVisitor.METHOD_DESCRIPTOR,
+                          desc );
+        if ( exceptions != null && exceptions.length > 0 ) {
+            this.buf.append( " throws " );
+            for ( int i = 0; i < exceptions.length; ++i ) {
+                appendDescriptor( TraceAbstractVisitor.INTERNAL_NAME,
+                                  exceptions[i] );
+                this.buf.append( ' ' );
+            }
+        }
+
+        this.buf.append( '\n' );
+        this.text.add( this.buf.toString() );
+
+        final TraceMethodVisitor tcv = createTraceMethodVisitor();
+        this.text.add( tcv.getText() );
+
+        if ( this.cv != null ) {
+            tcv.mv = this.cv.visitMethod( access,
+                                          name,
+                                          desc,
+                                          signature,
+                                          exceptions );
+        }
+
+        return tcv;
+    }
+
+    public void visitEnd() {
+        this.text.add( "}\n" );
+
+        printList( this.pw,
+                   this.text );
+        this.pw.flush();
+
+        if ( this.cv != null ) {
+            this.cv.visitEnd();
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods
+    // ------------------------------------------------------------------------
+
+    protected TraceFieldVisitor createTraceFieldVisitor() {
+        return new TraceFieldVisitor();
+    }
+
+    protected TraceMethodVisitor createTraceMethodVisitor() {
+        return new TraceMethodVisitor();
+    }
+
+    /**
+     * Appends a string representation of the given access modifiers to {@link
+     * #buf buf}.
+     * 
+     * @param access some access modifiers.
+     */
+    private void appendAccess(final int access) {
+        if ( (access & Opcodes.ACC_PUBLIC) != 0 ) {
+            this.buf.append( "public " );
+        }
+        if ( (access & Opcodes.ACC_PRIVATE) != 0 ) {
+            this.buf.append( "private " );
+        }
+        if ( (access & Opcodes.ACC_PROTECTED) != 0 ) {
+            this.buf.append( "protected " );
+        }
+        if ( (access & Opcodes.ACC_FINAL) != 0 ) {
+            this.buf.append( "final " );
+        }
+        if ( (access & Opcodes.ACC_STATIC) != 0 ) {
+            this.buf.append( "static " );
+        }
+        if ( (access & Opcodes.ACC_SYNCHRONIZED) != 0 ) {
+            this.buf.append( "synchronized " );
+        }
+        if ( (access & Opcodes.ACC_VOLATILE) != 0 ) {
+            this.buf.append( "volatile " );
+        }
+        if ( (access & Opcodes.ACC_TRANSIENT) != 0 ) {
+            this.buf.append( "transient " );
+        }
+        // if ((access & Constants.ACC_NATIVE) != 0) {
+        // buf.append("native ");
+        // }
+        if ( (access & Opcodes.ACC_ABSTRACT) != 0 ) {
+            this.buf.append( "abstract " );
+        }
+        if ( (access & Opcodes.ACC_STRICT) != 0 ) {
+            this.buf.append( "strictfp " );
+        }
+        if ( (access & Opcodes.ACC_SYNTHETIC) != 0 ) {
+            this.buf.append( "synthetic " );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceFieldVisitor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceFieldVisitor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceFieldVisitor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,78 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.util;
+
+import org.drools.asm.AnnotationVisitor;
+import org.drools.asm.Attribute;
+import org.drools.asm.FieldVisitor;
+
+/**
+ * A {@link FieldVisitor} that prints a disassembled view of the fields it
+ * visits.
+ * 
+ * @author Eric Bruneton
+ */
+public class TraceFieldVisitor extends TraceAbstractVisitor
+    implements
+    FieldVisitor {
+
+    /**
+     * The {@link FieldVisitor} to which this visitor delegates calls. May be
+     * <tt>null</tt>.
+     */
+    protected FieldVisitor fv;
+
+    public AnnotationVisitor visitAnnotation(final String desc,
+                                             final boolean visible) {
+        final AnnotationVisitor av = super.visitAnnotation( desc,
+                                                            visible );
+        if ( this.fv != null ) {
+            ((TraceAnnotationVisitor) av).av = this.fv.visitAnnotation( desc,
+                                                                        visible );
+        }
+        return av;
+    }
+
+    public void visitAttribute(final Attribute attr) {
+        super.visitAttribute( attr );
+
+        if ( this.fv != null ) {
+            this.fv.visitAttribute( attr );
+        }
+    }
+
+    public void visitEnd() {
+        super.visitEnd();
+
+        if ( this.fv != null ) {
+            this.fv.visitEnd();
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceMethodVisitor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceMethodVisitor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceMethodVisitor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,506 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.util;
+
+import java.util.HashMap;
+
+import org.drools.asm.AnnotationVisitor;
+import org.drools.asm.Attribute;
+import org.drools.asm.Label;
+import org.drools.asm.MethodVisitor;
+import org.drools.asm.Opcodes;
+import org.drools.asm.Type;
+import org.drools.asm.signature.SignatureReader;
+import org.drools.asm.util.attrs.Traceable;
+
+/**
+ * A {@link MethodVisitor} that prints a disassembled view of the methods it
+ * visits.
+ * 
+ * @author Eric Bruneton
+ */
+public class TraceMethodVisitor extends TraceAbstractVisitor
+    implements
+    MethodVisitor {
+
+    /**
+     * The {@link MethodVisitor} to which this visitor delegates calls. May be
+     * <tt>null</tt>.
+     */
+    protected MethodVisitor mv;
+
+    /**
+     * Tab for bytecode instructions.
+     */
+    protected String        tab2 = "    ";
+
+    /**
+     * Tab for table and lookup switch instructions.
+     */
+    protected String        tab3 = "      ";
+
+    /**
+     * Tab for labels.
+     */
+    protected String        ltab = "   ";
+
+    /**
+     * The label names. This map associate String values to Label keys.
+     */
+    protected final HashMap labelNames;
+
+    /**
+     * Constructs a new {@link TraceMethodVisitor}.
+     */
+    public TraceMethodVisitor() {
+        this( null );
+    }
+
+    /**
+     * Constructs a new {@link TraceMethodVisitor}.
+     * 
+     * @param mv the {@link MethodVisitor} to which this visitor delegates
+     *        calls. May be <tt>null</tt>.
+     */
+    public TraceMethodVisitor(final MethodVisitor mv) {
+        this.labelNames = new HashMap();
+        this.mv = mv;
+    }
+
+    // ------------------------------------------------------------------------
+    // Implementation of the MethodVisitor interface
+    // ------------------------------------------------------------------------
+
+    public AnnotationVisitor visitAnnotation(final String desc,
+                                             final boolean visible) {
+        final AnnotationVisitor av = super.visitAnnotation( desc,
+                                                            visible );
+        if ( this.mv != null ) {
+            ((TraceAnnotationVisitor) av).av = this.mv.visitAnnotation( desc,
+                                                                        visible );
+        }
+        return av;
+    }
+
+    public void visitAttribute(final Attribute attr) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab ).append( "ATTRIBUTE " );
+        appendDescriptor( -1,
+                          attr.type );
+
+        if ( attr instanceof Traceable ) {
+            ((Traceable) attr).trace( this.buf,
+                                      this.labelNames );
+        } else {
+            this.buf.append( " : " ).append( attr.toString() ).append( "\n" );
+        }
+
+        this.text.add( this.buf.toString() );
+        if ( this.mv != null ) {
+            this.mv.visitAttribute( attr );
+        }
+    }
+
+    public AnnotationVisitor visitAnnotationDefault() {
+        this.text.add( this.tab2 + "default=" );
+        final TraceAnnotationVisitor tav = new TraceAnnotationVisitor();
+        this.text.add( tav.getText() );
+        this.text.add( "\n" );
+        if ( this.mv != null ) {
+            tav.av = this.mv.visitAnnotationDefault();
+        }
+        return tav;
+    }
+
+    public AnnotationVisitor visitParameterAnnotation(final int parameter,
+                                                      final String desc,
+                                                      final boolean visible) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab2 ).append( '@' );
+        appendDescriptor( TraceAbstractVisitor.FIELD_DESCRIPTOR,
+                          desc );
+        this.buf.append( '(' );
+        this.text.add( this.buf.toString() );
+        final TraceAnnotationVisitor tav = new TraceAnnotationVisitor();
+        this.text.add( tav.getText() );
+        this.text.add( visible ? ") // parameter " : ") // invisible, parameter " );
+        this.text.add( new Integer( parameter ) );
+        this.text.add( "\n" );
+        if ( this.mv != null ) {
+            tav.av = this.mv.visitParameterAnnotation( parameter,
+                                                       desc,
+                                                       visible );
+        }
+        return tav;
+    }
+
+    public void visitCode() {
+        if ( this.mv != null ) {
+            this.mv.visitCode();
+        }
+    }
+
+    public void visitInsn(final int opcode) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab2 ).append( AbstractVisitor.OPCODES[opcode] ).append( '\n' );
+        this.text.add( this.buf.toString() );
+
+        if ( this.mv != null ) {
+            this.mv.visitInsn( opcode );
+        }
+    }
+
+    public void visitIntInsn(final int opcode,
+                             final int operand) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab2 ).append( AbstractVisitor.OPCODES[opcode] ).append( ' ' ).append( opcode == Opcodes.NEWARRAY ? AbstractVisitor.TYPES[operand] : Integer.toString( operand ) ).append( '\n' );
+        this.text.add( this.buf.toString() );
+
+        if ( this.mv != null ) {
+            this.mv.visitIntInsn( opcode,
+                                  operand );
+        }
+    }
+
+    public void visitVarInsn(final int opcode,
+                             final int var) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab2 ).append( AbstractVisitor.OPCODES[opcode] ).append( ' ' ).append( var ).append( '\n' );
+        this.text.add( this.buf.toString() );
+
+        if ( this.mv != null ) {
+            this.mv.visitVarInsn( opcode,
+                                  var );
+        }
+    }
+
+    public void visitTypeInsn(final int opcode,
+                              final String desc) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab2 ).append( AbstractVisitor.OPCODES[opcode] ).append( ' ' );
+        if ( desc.startsWith( "[" ) ) {
+            appendDescriptor( TraceAbstractVisitor.FIELD_DESCRIPTOR,
+                              desc );
+        } else {
+            appendDescriptor( TraceAbstractVisitor.INTERNAL_NAME,
+                              desc );
+        }
+        this.buf.append( '\n' );
+        this.text.add( this.buf.toString() );
+
+        if ( this.mv != null ) {
+            this.mv.visitTypeInsn( opcode,
+                                   desc );
+        }
+    }
+
+    public void visitFieldInsn(final int opcode,
+                               final String owner,
+                               final String name,
+                               final String desc) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab2 ).append( AbstractVisitor.OPCODES[opcode] ).append( ' ' );
+        appendDescriptor( TraceAbstractVisitor.INTERNAL_NAME,
+                          owner );
+        this.buf.append( '.' ).append( name ).append( " : " );
+        appendDescriptor( TraceAbstractVisitor.FIELD_DESCRIPTOR,
+                          desc );
+        this.buf.append( '\n' );
+        this.text.add( this.buf.toString() );
+
+        if ( this.mv != null ) {
+            this.mv.visitFieldInsn( opcode,
+                                    owner,
+                                    name,
+                                    desc );
+        }
+    }
+
+    public void visitMethodInsn(final int opcode,
+                                final String owner,
+                                final String name,
+                                final String desc) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab2 ).append( AbstractVisitor.OPCODES[opcode] ).append( ' ' );
+        appendDescriptor( TraceAbstractVisitor.INTERNAL_NAME,
+                          owner );
+        this.buf.append( '.' ).append( name ).append( ' ' );
+        appendDescriptor( TraceAbstractVisitor.METHOD_DESCRIPTOR,
+                          desc );
+        this.buf.append( '\n' );
+        this.text.add( this.buf.toString() );
+
+        if ( this.mv != null ) {
+            this.mv.visitMethodInsn( opcode,
+                                     owner,
+                                     name,
+                                     desc );
+        }
+    }
+
+    public void visitJumpInsn(final int opcode,
+                              final Label label) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab2 ).append( AbstractVisitor.OPCODES[opcode] ).append( ' ' );
+        appendLabel( label );
+        this.buf.append( '\n' );
+        this.text.add( this.buf.toString() );
+
+        if ( this.mv != null ) {
+            this.mv.visitJumpInsn( opcode,
+                                   label );
+        }
+    }
+
+    public void visitLabel(final Label label) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.ltab );
+        appendLabel( label );
+        this.buf.append( '\n' );
+        this.text.add( this.buf.toString() );
+
+        if ( this.mv != null ) {
+            this.mv.visitLabel( label );
+        }
+    }
+
+    public void visitLdcInsn(final Object cst) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab2 ).append( "LDC " );
+        if ( cst instanceof String ) {
+            AbstractVisitor.appendString( this.buf,
+                                          (String) cst );
+        } else if ( cst instanceof Type ) {
+            this.buf.append( ((Type) cst).getDescriptor() + ".class" );
+        } else {
+            this.buf.append( cst );
+        }
+        this.buf.append( '\n' );
+        this.text.add( this.buf.toString() );
+
+        if ( this.mv != null ) {
+            this.mv.visitLdcInsn( cst );
+        }
+    }
+
+    public void visitIincInsn(final int var,
+                              final int increment) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab2 ).append( "IINC " ).append( var ).append( ' ' ).append( increment ).append( '\n' );
+        this.text.add( this.buf.toString() );
+
+        if ( this.mv != null ) {
+            this.mv.visitIincInsn( var,
+                                   increment );
+        }
+    }
+
+    public void visitTableSwitchInsn(final int min,
+                                     final int max,
+                                     final Label dflt,
+                                     final Label labels[]) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab2 ).append( "TABLESWITCH\n" );
+        for ( int i = 0; i < labels.length; ++i ) {
+            this.buf.append( this.tab3 ).append( min + i ).append( ": " );
+            appendLabel( labels[i] );
+            this.buf.append( '\n' );
+        }
+        this.buf.append( this.tab3 ).append( "default: " );
+        appendLabel( dflt );
+        this.buf.append( '\n' );
+        this.text.add( this.buf.toString() );
+
+        if ( this.mv != null ) {
+            this.mv.visitTableSwitchInsn( min,
+                                          max,
+                                          dflt,
+                                          labels );
+        }
+    }
+
+    public void visitLookupSwitchInsn(final Label dflt,
+                                      final int keys[],
+                                      final Label labels[]) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab2 ).append( "LOOKUPSWITCH\n" );
+        for ( int i = 0; i < labels.length; ++i ) {
+            this.buf.append( this.tab3 ).append( keys[i] ).append( ": " );
+            appendLabel( labels[i] );
+            this.buf.append( '\n' );
+        }
+        this.buf.append( this.tab3 ).append( "default: " );
+        appendLabel( dflt );
+        this.buf.append( '\n' );
+        this.text.add( this.buf.toString() );
+
+        if ( this.mv != null ) {
+            this.mv.visitLookupSwitchInsn( dflt,
+                                           keys,
+                                           labels );
+        }
+    }
+
+    public void visitMultiANewArrayInsn(final String desc,
+                                        final int dims) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab2 ).append( "MULTIANEWARRAY " );
+        appendDescriptor( TraceAbstractVisitor.FIELD_DESCRIPTOR,
+                          desc );
+        this.buf.append( ' ' ).append( dims ).append( '\n' );
+        this.text.add( this.buf.toString() );
+
+        if ( this.mv != null ) {
+            this.mv.visitMultiANewArrayInsn( desc,
+                                             dims );
+        }
+    }
+
+    public void visitTryCatchBlock(final Label start,
+                                   final Label end,
+                                   final Label handler,
+                                   final String type) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab2 ).append( "TRYCATCHBLOCK " );
+        appendLabel( start );
+        this.buf.append( ' ' );
+        appendLabel( end );
+        this.buf.append( ' ' );
+        appendLabel( handler );
+        this.buf.append( ' ' );
+        appendDescriptor( TraceAbstractVisitor.INTERNAL_NAME,
+                          type );
+        this.buf.append( '\n' );
+        this.text.add( this.buf.toString() );
+
+        if ( this.mv != null ) {
+            this.mv.visitTryCatchBlock( start,
+                                        end,
+                                        handler,
+                                        type );
+        }
+    }
+
+    public void visitLocalVariable(final String name,
+                                   final String desc,
+                                   final String signature,
+                                   final Label start,
+                                   final Label end,
+                                   final int index) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab2 ).append( "LOCALVARIABLE " ).append( name ).append( ' ' );
+        appendDescriptor( TraceAbstractVisitor.FIELD_DESCRIPTOR,
+                          desc );
+        this.buf.append( ' ' );
+        appendLabel( start );
+        this.buf.append( ' ' );
+        appendLabel( end );
+        this.buf.append( ' ' ).append( index ).append( '\n' );
+
+        if ( signature != null ) {
+            this.buf.append( this.tab2 );
+            appendDescriptor( TraceAbstractVisitor.FIELD_SIGNATURE,
+                              signature );
+
+            final TraceSignatureVisitor sv = new TraceSignatureVisitor( 0 );
+            final SignatureReader r = new SignatureReader( signature );
+            r.acceptType( sv );
+            this.buf.append( this.tab2 ).append( "// declaration: " ).append( sv.getDeclaration() ).append( '\n' );
+        }
+        this.text.add( this.buf.toString() );
+
+        if ( this.mv != null ) {
+            this.mv.visitLocalVariable( name,
+                                        desc,
+                                        signature,
+                                        start,
+                                        end,
+                                        index );
+        }
+    }
+
+    public void visitLineNumber(final int line,
+                                final Label start) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab2 ).append( "LINENUMBER " ).append( line ).append( ' ' );
+        appendLabel( start );
+        this.buf.append( '\n' );
+        this.text.add( this.buf.toString() );
+
+        if ( this.mv != null ) {
+            this.mv.visitLineNumber( line,
+                                     start );
+        }
+    }
+
+    public void visitMaxs(final int maxStack,
+                          final int maxLocals) {
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab2 ).append( "MAXSTACK = " ).append( maxStack ).append( '\n' );
+        this.text.add( this.buf.toString() );
+
+        this.buf.setLength( 0 );
+        this.buf.append( this.tab2 ).append( "MAXLOCALS = " ).append( maxLocals ).append( '\n' );
+        this.text.add( this.buf.toString() );
+
+        if ( this.mv != null ) {
+            this.mv.visitMaxs( maxStack,
+                               maxLocals );
+        }
+    }
+
+    public void visitEnd() {
+        super.visitEnd();
+
+        if ( this.mv != null ) {
+            this.mv.visitEnd();
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Utility methods
+    // ------------------------------------------------------------------------
+
+    /**
+     * Appends the name of the given label to {@link #buf buf}. Creates a new
+     * label name if the given label does not yet have one.
+     * 
+     * @param l a label.
+     */
+    public void appendLabel(final Label l) {
+        String name = (String) this.labelNames.get( l );
+        if ( name == null ) {
+            name = "L" + this.labelNames.size();
+            this.labelNames.put( l,
+                                 name );
+        }
+        this.buf.append( name );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceSignatureVisitor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceSignatureVisitor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/TraceSignatureVisitor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,293 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.util;
+
+import org.drools.asm.Opcodes;
+import org.drools.asm.signature.SignatureVisitor;
+
+public class TraceSignatureVisitor
+    implements
+    SignatureVisitor {
+
+    private StringBuffer declaration;
+
+    private boolean      isInterface;
+
+    private boolean      seenFormalParameter;
+
+    private boolean      seenInterfaceBound;
+
+    private boolean      seenParameter;
+
+    private boolean      seenInterface;
+
+    private StringBuffer returnType;
+
+    private StringBuffer exceptions;
+
+    /**
+     * Stack used to keep track of class types that have arguments. Each element
+     * of this stack is a boolean encoded in one bit. The top of the stack is
+     * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping =
+     * /2.
+     */
+    private int          argumentStack;
+
+    /**
+     * Stack used to keep track of array class types. Each element of this stack
+     * is a boolean encoded in one bit. The top of the stack is the lowest order
+     * bit. Pushing false = *2, pushing true = *2+1, popping = /2.
+     */
+    private int          arrayStack;
+
+    private String       separator = "";
+
+    public TraceSignatureVisitor(final int access) {
+        this.isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
+        this.declaration = new StringBuffer();
+    }
+
+    private TraceSignatureVisitor(final StringBuffer buf) {
+        this.declaration = buf;
+    }
+
+    public void visitFormalTypeParameter(final String name) {
+        this.declaration.append( this.seenFormalParameter ? ", " : "<" ).append( name );
+        this.seenFormalParameter = true;
+        this.seenInterfaceBound = false;
+    }
+
+    public SignatureVisitor visitClassBound() {
+        this.separator = " extends ";
+        startType();
+        return this;
+    }
+
+    public SignatureVisitor visitInterfaceBound() {
+        this.separator = this.seenInterfaceBound ? ", " : " extends ";
+        this.seenInterfaceBound = true;
+        startType();
+        return this;
+    }
+
+    public SignatureVisitor visitSuperclass() {
+        endFormals();
+        this.separator = " extends ";
+        startType();
+        return this;
+    }
+
+    public SignatureVisitor visitInterface() {
+        this.separator = this.seenInterface ? ", " : (this.isInterface ? " extends " : " implements ");
+        this.seenInterface = true;
+        startType();
+        return this;
+    }
+
+    public SignatureVisitor visitParameterType() {
+        endFormals();
+        if ( !this.seenParameter ) {
+            this.seenParameter = true;
+            this.declaration.append( '(' );
+        } else {
+            this.declaration.append( ", " );
+        }
+        startType();
+        return this;
+    }
+
+    public SignatureVisitor visitReturnType() {
+        endFormals();
+        if ( !this.seenParameter ) {
+            this.declaration.append( '(' );
+        } else {
+            this.seenParameter = false;
+        }
+        this.declaration.append( ')' );
+        this.returnType = new StringBuffer();
+        return new TraceSignatureVisitor( this.returnType );
+    }
+
+    public SignatureVisitor visitExceptionType() {
+        if ( this.exceptions == null ) {
+            this.exceptions = new StringBuffer();
+        } else {
+            this.exceptions.append( ", " );
+        }
+        // startType();
+        return new TraceSignatureVisitor( this.exceptions );
+    }
+
+    public void visitBaseType(final char descriptor) {
+        switch ( descriptor ) {
+            case 'V' :
+                this.declaration.append( "void" );
+                break;
+            case 'B' :
+                this.declaration.append( "byte" );
+                break;
+            case 'J' :
+                this.declaration.append( "long" );
+                break;
+            case 'Z' :
+                this.declaration.append( "boolean" );
+                break;
+            case 'I' :
+                this.declaration.append( "int" );
+                break;
+            case 'S' :
+                this.declaration.append( "short" );
+                break;
+            case 'C' :
+                this.declaration.append( "char" );
+                break;
+            case 'F' :
+                this.declaration.append( "float" );
+                break;
+            case 'D' :
+                this.declaration.append( "double" );
+                break;
+            default :
+                throw new IllegalArgumentException( "Invalid descriptor " + descriptor );
+        }
+        endType();
+    }
+
+    public void visitTypeVariable(final String name) {
+        this.declaration.append( name );
+        endType();
+    }
+
+    public SignatureVisitor visitArrayType() {
+        startType();
+        this.arrayStack |= 1;
+        return this;
+    }
+
+    public void visitClassType(final String name) {
+        if ( !"java/lang/Object".equals( name ) ) {
+            this.declaration.append( this.separator ).append( name.replace( '/',
+                                                                            '.' ) );
+        } else {
+            // Map<java.lang.Object,java.util.List>
+            // or
+            // abstract public V get(Object key); (seen in Dictionary.class)
+            // should have Object
+            // but java.lang.String extends java.lang.Object is unnecessary
+            final boolean needObjectClass = this.argumentStack % 2 == 1 || this.seenParameter;
+            if ( needObjectClass ) {
+                this.declaration.append( this.separator ).append( name.replace( '/',
+                                                                                '.' ) );
+            }
+        }
+        this.separator = "";
+        this.argumentStack *= 2;
+    }
+
+    public void visitInnerClassType(final String name) {
+        // TODO tests
+        this.declaration.append( this.separator ).append( name.replace( '/',
+                                                                        '.' ) );
+        this.separator = "";
+        this.argumentStack *= 2;
+    }
+
+    public void visitTypeArgument() {
+        if ( this.argumentStack % 2 == 0 ) {
+            ++this.argumentStack;
+            this.declaration.append( "<" );
+        } else {
+            this.declaration.append( ", " );
+        }
+        this.declaration.append( "?" );
+    }
+
+    public SignatureVisitor visitTypeArgument(final char tag) {
+        if ( this.argumentStack % 2 == 0 ) {
+            ++this.argumentStack;
+            this.declaration.append( "<" );
+        } else {
+            this.declaration.append( ", " );
+        }
+
+        if ( tag == SignatureVisitor.EXTENDS ) {
+            this.declaration.append( "? extends " );
+        } else if ( tag == SignatureVisitor.SUPER ) {
+            this.declaration.append( "? super " );
+        }
+
+        startType();
+        return this;
+    }
+
+    public void visitEnd() {
+        if ( this.argumentStack % 2 == 1 ) {
+            this.declaration.append( ">" );
+        }
+        this.argumentStack /= 2;
+        endType();
+    }
+
+    public String getDeclaration() {
+        return this.declaration.toString();
+    }
+
+    public String getReturnType() {
+        return this.returnType == null ? null : this.returnType.toString();
+    }
+
+    public String getExceptions() {
+        return this.exceptions == null ? null : this.exceptions.toString();
+    }
+
+    // -----------------------------------------------
+
+    private void endFormals() {
+        if ( this.seenFormalParameter ) {
+            this.declaration.append( ">" );
+            this.seenFormalParameter = false;
+        }
+    }
+
+    private void startType() {
+        this.arrayStack *= 2;
+    }
+
+    private void endType() {
+        if ( this.arrayStack % 2 == 1 ) {
+            while ( this.arrayStack % 2 == 1 ) {
+                this.arrayStack /= 2;
+                this.declaration.append( "[]" );
+            }
+        } else {
+            this.arrayStack /= 2;
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/attrs/ASMStackMapAttribute.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/attrs/ASMStackMapAttribute.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/attrs/ASMStackMapAttribute.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,232 @@
+/**
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.util.attrs;
+
+import java.util.List;
+import java.util.Map;
+
+import org.drools.asm.Attribute;
+import org.drools.asm.ClassReader;
+import org.drools.asm.Label;
+import org.drools.asm.attrs.StackMapAttribute;
+import org.drools.asm.attrs.StackMapFrame;
+import org.drools.asm.attrs.StackMapType;
+
+/**
+ * An {@link ASMifiable} {@link StackMapAttribute} sub class.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class ASMStackMapAttribute extends StackMapAttribute
+    implements
+    ASMifiable,
+    Traceable {
+    /**
+     * Length of the attribute used for comparison
+     */
+    private int len;
+
+    public ASMStackMapAttribute() {
+        super();
+    }
+
+    public ASMStackMapAttribute(final List frames,
+                                final int len) {
+        super( frames );
+        this.len = len;
+    }
+
+    protected Attribute read(final ClassReader cr,
+                             final int off,
+                             final int len,
+                             final char[] buf,
+                             final int codeOff,
+                             final Label[] labels) {
+        final StackMapAttribute attr = (StackMapAttribute) super.read( cr,
+                                                                       off,
+                                                                       len,
+                                                                       buf,
+                                                                       codeOff,
+                                                                       labels );
+
+        return new ASMStackMapAttribute( attr.getFrames(),
+                                         len );
+    }
+
+    public void asmify(final StringBuffer buf,
+                       final String varName,
+                       final Map labelNames) {
+        final List frames = getFrames();
+        buf.append( "{\n" );
+        buf.append( "StackMapAttribute " ).append( varName ).append( "Attr" );
+        buf.append( " = new StackMapAttribute();\n" );
+        if ( frames.size() > 0 ) {
+            for ( int i = 0; i < frames.size(); i++ ) {
+                asmify( (StackMapFrame) frames.get( i ),
+                        buf,
+                        varName + "frame" + i,
+                        labelNames );
+            }
+        }
+        buf.append( varName ).append( ".visitAttribute(" ).append( varName );
+        buf.append( "Attr);\n}\n" );
+    }
+
+    void asmify(final StackMapFrame f,
+                final StringBuffer buf,
+                final String varName,
+                final Map labelNames) {
+        declareLabel( buf,
+                      labelNames,
+                      f.label );
+        buf.append( "{\n" );
+
+        buf.append( "StackMapFrame " ).append( varName ).append( " = new StackMapFrame();\n" );
+
+        buf.append( varName ).append( ".label = " ).append( labelNames.get( f.label ) ).append( ";\n" );
+
+        asmifyTypeInfo( buf,
+                        varName,
+                        labelNames,
+                        f.locals,
+                        "locals" );
+        asmifyTypeInfo( buf,
+                        varName,
+                        labelNames,
+                        f.stack,
+                        "stack" );
+
+        buf.append( "cvAttr.frames.add(" ).append( varName ).append( ");\n" );
+        buf.append( "}\n" );
+    }
+
+    void asmifyTypeInfo(final StringBuffer buf,
+                        final String varName,
+                        final Map labelNames,
+                        final List infos,
+                        final String field) {
+        if ( infos.size() > 0 ) {
+            buf.append( "{\n" );
+            for ( int i = 0; i < infos.size(); i++ ) {
+                final StackMapType typeInfo = (StackMapType) infos.get( i );
+                final String localName = varName + "Info" + i;
+                final int type = typeInfo.getType();
+                buf.append( "StackMapType " ).append( localName ).append( " = StackMapType.getTypeInfo( StackMapType.ITEM_" ).append( StackMapType.ITEM_NAMES[type] ).append( ");\n" );
+
+                switch ( type ) {
+                    case StackMapType.ITEM_Object : //
+                        buf.append( localName ).append( ".setObject(\"" ).append( typeInfo.getObject() ).append( "\");\n" );
+                        break;
+
+                    case StackMapType.ITEM_Uninitialized : //
+                        declareLabel( buf,
+                                      labelNames,
+                                      typeInfo.getLabel() );
+                        buf.append( localName ).append( ".setLabel(" ).append( labelNames.get( typeInfo.getLabel() ) ).append( ");\n" );
+                        break;
+                }
+                buf.append( varName ).append( "." ).append( field ).append( ".add(" ).append( localName ).append( ");\n" );
+            }
+            buf.append( "}\n" );
+        }
+    }
+
+    static void declareLabel(final StringBuffer buf,
+                             final Map labelNames,
+                             final Label l) {
+        String name = (String) labelNames.get( l );
+        if ( name == null ) {
+            name = "l" + labelNames.size();
+            labelNames.put( l,
+                            name );
+            buf.append( "Label " ).append( name ).append( " = new Label();\n" );
+        }
+    }
+
+    public void trace(final StringBuffer buf,
+                      final Map labelNames) {
+        final List frames = getFrames();
+        buf.append( "[\n" );
+        for ( int i = 0; i < frames.size(); i++ ) {
+            final StackMapFrame f = (StackMapFrame) frames.get( i );
+
+            buf.append( "    Frame:" );
+            appendLabel( buf,
+                         labelNames,
+                         f.label );
+
+            buf.append( " locals[" );
+            traceTypeInfo( buf,
+                           labelNames,
+                           f.locals );
+            buf.append( "]" );
+            buf.append( " stack[" );
+            traceTypeInfo( buf,
+                           labelNames,
+                           f.stack );
+            buf.append( "]\n" );
+        }
+        buf.append( "  ] length:" ).append( this.len ).append( "\n" );
+    }
+
+    private void traceTypeInfo(final StringBuffer buf,
+                               final Map labelNames,
+                               final List infos) {
+        String sep = "";
+        for ( int i = 0; i < infos.size(); i++ ) {
+            final StackMapType t = (StackMapType) infos.get( i );
+
+            buf.append( sep ).append( StackMapType.ITEM_NAMES[t.getType()] );
+            sep = ", ";
+            if ( t.getType() == StackMapType.ITEM_Object ) {
+                buf.append( ":" ).append( t.getObject() );
+            }
+            if ( t.getType() == StackMapType.ITEM_Uninitialized ) {
+                buf.append( ":" );
+                appendLabel( buf,
+                             labelNames,
+                             t.getLabel() );
+            }
+        }
+    }
+
+    protected void appendLabel(final StringBuffer buf,
+                               final Map labelNames,
+                               final Label l) {
+        String name = (String) labelNames.get( l );
+        if ( name == null ) {
+            name = "L" + labelNames.size();
+            labelNames.put( l,
+                            name );
+        }
+        buf.append( name );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/attrs/ASMStackMapTableAttribute.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/attrs/ASMStackMapTableAttribute.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/attrs/ASMStackMapTableAttribute.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,224 @@
+/**
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.util.attrs;
+
+import java.util.List;
+import java.util.Map;
+
+import org.drools.asm.Attribute;
+import org.drools.asm.ClassReader;
+import org.drools.asm.Label;
+import org.drools.asm.attrs.StackMapFrame;
+import org.drools.asm.attrs.StackMapTableAttribute;
+import org.drools.asm.attrs.StackMapType;
+
+/**
+ * An {@link ASMifiable} {@link StackMapTableAttribute} sub class.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class ASMStackMapTableAttribute extends StackMapTableAttribute
+    implements
+    ASMifiable,
+    Traceable {
+    /**
+     * Length of the attribute used for comparison
+     */
+    private int len;
+
+    public ASMStackMapTableAttribute() {
+        super();
+    }
+
+    public ASMStackMapTableAttribute(final List frames,
+                                     final int len) {
+        super( frames );
+        this.len = len;
+    }
+
+    protected Attribute read(final ClassReader cr,
+                             final int off,
+                             final int len,
+                             final char[] buf,
+                             final int codeOff,
+                             final Label[] labels) {
+        final StackMapTableAttribute attr = (StackMapTableAttribute) super.read( cr,
+                                                                                 off,
+                                                                                 len,
+                                                                                 buf,
+                                                                                 codeOff,
+                                                                                 labels );
+
+        return new ASMStackMapTableAttribute( attr.getFrames(),
+                                              len );
+    }
+
+    public void asmify(final StringBuffer buf,
+                       final String varName,
+                       final Map labelNames) {
+        final List frames = getFrames();
+        if ( frames.size() == 0 ) {
+            buf.append( "List frames = Collections.EMPTY_LIST;\n" );
+        } else {
+            buf.append( "List frames = new ArrayList();\n" );
+            for ( int i = 0; i < frames.size(); i++ ) {
+                buf.append( "{\n" );
+                final StackMapFrame f = (StackMapFrame) frames.get( i );
+                declareLabel( buf,
+                              labelNames,
+                              f.label );
+
+                final String frameVar = varName + "frame" + i;
+                asmifyTypeInfo( buf,
+                                frameVar,
+                                labelNames,
+                                f.locals,
+                                "locals" );
+                asmifyTypeInfo( buf,
+                                frameVar,
+                                labelNames,
+                                f.stack,
+                                "stack" );
+
+                buf.append( "StackMapFrame " ).append( frameVar ).append( " = new StackMapFrame(" ).append( labelNames.get( f.label ) ).append( ", locals, stack);\n" );
+                buf.append( "frames.add(" ).append( frameVar ).append( ");\n" );
+                buf.append( "}\n" );
+            }
+        }
+        buf.append( "StackMapTableAttribute " ).append( varName );
+        buf.append( " = new StackMapTableAttribute(frames);\n" );
+    }
+
+    void asmifyTypeInfo(final StringBuffer buf,
+                        final String varName,
+                        final Map labelNames,
+                        final List infos,
+                        final String field) {
+        if ( infos.size() == 0 ) {
+            buf.append( "List " ).append( field ).append( " = Collections.EMPTY_LIST;\n" );
+        } else {
+            buf.append( "List " ).append( field ).append( " = new ArrayList();\n" );
+            buf.append( "{\n" );
+            for ( int i = 0; i < infos.size(); i++ ) {
+                final StackMapType typeInfo = (StackMapType) infos.get( i );
+                final String localName = varName + "Info" + i;
+                final int type = typeInfo.getType();
+                buf.append( "StackMapType " ).append( localName ).append( " = StackMapType.getTypeInfo( StackMapType.ITEM_" ).append( StackMapType.ITEM_NAMES[type] ).append( ");\n" );
+
+                switch ( type ) {
+                    case StackMapType.ITEM_Object : //
+                        buf.append( localName ).append( ".setObject(\"" ).append( typeInfo.getObject() ).append( "\");\n" );
+                        break;
+
+                    case StackMapType.ITEM_Uninitialized : //
+                        declareLabel( buf,
+                                      labelNames,
+                                      typeInfo.getLabel() );
+                        buf.append( localName ).append( ".setLabel(" ).append( labelNames.get( typeInfo.getLabel() ) ).append( ");\n" );
+                        break;
+                }
+                buf.append( field ).append( ".add(" ).append( localName ).append( ");\n" );
+            }
+            buf.append( "}\n" );
+        }
+    }
+
+    static void declareLabel(final StringBuffer buf,
+                             final Map labelNames,
+                             final Label l) {
+        String name = (String) labelNames.get( l );
+        if ( name == null ) {
+            name = "l" + labelNames.size();
+            labelNames.put( l,
+                            name );
+            buf.append( "Label " ).append( name ).append( " = new Label();\n" );
+        }
+    }
+
+    public void trace(final StringBuffer buf,
+                      final Map labelNames) {
+        final List frames = getFrames();
+        buf.append( "[\n" );
+        for ( int i = 0; i < frames.size(); i++ ) {
+            final StackMapFrame f = (StackMapFrame) frames.get( i );
+
+            buf.append( "    Frame:" );
+            appendLabel( buf,
+                         labelNames,
+                         f.label );
+
+            buf.append( " locals[" );
+            traceTypeInfo( buf,
+                           labelNames,
+                           f.locals );
+            buf.append( "]" );
+            buf.append( " stack[" );
+            traceTypeInfo( buf,
+                           labelNames,
+                           f.stack );
+            buf.append( "]\n" );
+        }
+        buf.append( "  ] length:" ).append( this.len ).append( "\n" );
+    }
+
+    private void traceTypeInfo(final StringBuffer buf,
+                               final Map labelNames,
+                               final List infos) {
+        String sep = "";
+        for ( int i = 0; i < infos.size(); i++ ) {
+            final StackMapType t = (StackMapType) infos.get( i );
+
+            buf.append( sep ).append( StackMapType.ITEM_NAMES[t.getType()] );
+            sep = ", ";
+            if ( t.getType() == StackMapType.ITEM_Object ) {
+                buf.append( ":" ).append( t.getObject() );
+            }
+            if ( t.getType() == StackMapType.ITEM_Uninitialized ) {
+                buf.append( ":" );
+                appendLabel( buf,
+                             labelNames,
+                             t.getLabel() );
+            }
+        }
+    }
+
+    protected void appendLabel(final StringBuffer buf,
+                               final Map labelNames,
+                               final Label l) {
+        String name = (String) labelNames.get( l );
+        if ( name == null ) {
+            name = "L" + labelNames.size();
+            labelNames.put( l,
+                            name );
+        }
+        buf.append( name );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/attrs/ASMifiable.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/attrs/ASMifiable.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/attrs/ASMifiable.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,55 @@
+/**
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.util.attrs;
+
+import java.util.Map;
+
+/**
+ * An attribute that can print the ASM code to create an equivalent attribute.
+ * 
+ * Implementation should print the ASM code that generates attribute data
+ * structures for current attribute state.
+ * 
+ * @author Eugene Kuleshov
+ */
+public interface ASMifiable {
+
+    /**
+     * Prints the ASM code to create an attribute equal to this attribute.
+     * 
+     * @param buf A buffer used for printing Java code.
+     * @param varName name of the variable in a printed code used to store
+     *        attribute instance.
+     * @param labelNames map of label instances to their names.
+     */
+    void asmify(StringBuffer buf,
+                String varName,
+                Map labelNames);
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/attrs/Traceable.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/attrs/Traceable.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/attrs/Traceable.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,53 @@
+/**
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.drools.asm.util.attrs;
+
+import java.util.Map;
+
+/**
+ * An attribute that can print eadable representation of the attribute.
+ * 
+ * Implementation should construct readable output from an attribute data
+ * structures for current attribute state. Such representation could be used in
+ * unit test assertions.
+ * 
+ * @author Eugene Kuleshov
+ */
+public interface Traceable {
+
+    /**
+     * Build a human readable representation of the attribute.
+     * 
+     * @param buf A buffer used for printing Java code.
+     * @param labelNames map of label instances to their names.
+     */
+    void trace(StringBuffer buf,
+               Map labelNames);
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/attrs/package.html
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/attrs/package.html	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/attrs/package.html	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,36 @@
+<html>
+<!--
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<body>
+Provides attributes sub classes that can work with the ASMifier utility.
+
+ at since ASM 1.4.3
+</body>
+</html>

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/package.html
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/package.html	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/asm/util/package.html	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,40 @@
+<html>
+<!--
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<body>
+Provides ASM visitors that can be useful for programming and
+debugging purposes. These class visitors are normally not used by applications
+at runtime. This is why they are bundled in an optional <tt>asm-util.jar</tt>
+library that is separated from (but requires) the <tt>asm.jar</tt> library,
+which contains the core ASM framework.
+
+ at since ASM 1.3.2
+</body>
+</html>

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/WorkingMemoryConsoleLogger.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/WorkingMemoryConsoleLogger.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/WorkingMemoryConsoleLogger.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,16 @@
+package org.drools.audit;
+
+import org.drools.WorkingMemory;
+import org.drools.audit.event.LogEvent;
+
+public class WorkingMemoryConsoleLogger extends WorkingMemoryLogger {
+
+	public WorkingMemoryConsoleLogger(WorkingMemory workingMemory) {
+		super(workingMemory);
+	}
+	
+	public void logEventCreated(LogEvent logEvent) {
+		System.out.println(logEvent);
+	}
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/WorkingMemoryFileLogger.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/WorkingMemoryFileLogger.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/WorkingMemoryFileLogger.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,126 @@
+package org.drools.audit;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.WorkingMemoryEventManager;
+import org.drools.audit.event.LogEvent;
+
+import com.thoughtworks.xstream.XStream;
+
+/**
+ * A logger of events generated by a working memory.
+ * It stores its information in a file that can be specified.
+ * All the events logged are written to the file when the
+ * writeToDisk() method is invoked.  The log will contain all
+ * the events logged serialized to XML using XStream.
+ * Every time a new logger is created, the old event log will
+ * be overwritten.
+ * 
+ * TODO: make this class more scalable, for example
+ *  - logging to several files if log becomes too large
+ *  - automatically write updates to file at certain time intervals
+ *  - ...
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen </a>
+ */
+public class WorkingMemoryFileLogger extends WorkingMemoryLogger {
+
+    private final List events            = new ArrayList();
+    private String     fileName          = "event";
+    private int        maxEventsInMemory = 1000;
+    private int        nbOfFile          = 0;
+
+    /**
+     * Creates a new WorkingMemoryFileLogger for the given working memory.
+     * @param workingMemory
+     */
+    public WorkingMemoryFileLogger(final WorkingMemoryEventManager workingMemoryEventManager) {
+        super( workingMemoryEventManager );
+    }
+
+    /**
+     * Sets the name of the file the events are logged in.
+     * No extensions should be given since .log is automatically appended
+     * to the file name.
+     * The default is an event.log file in the current working directory.
+     * This can be a path relative to the current working directory
+     * (e.g. "mydir/subDir/myLogFile"), or an absolute path 
+     * (e.g. "C:/myLogFile").
+     * 
+     * @param fileName The name of the file the events should be logged in.
+     */
+    public void setFileName(final String fileName) {
+        this.fileName = fileName;
+    }
+
+    /**
+     * All events in the log are written to file.
+     * The log is automatically cleared afterwards.
+     */
+    public void writeToDisk() {
+        ObjectOutputStream out = null; 
+        try {
+            final XStream xstream = new XStream();
+            out = xstream.createObjectOutputStream( new FileWriter( this.fileName + (this.nbOfFile == 0 ? ".log" : this.nbOfFile + ".log"),
+                                                                                             false ) );
+            out.writeObject( this.events );
+            this.nbOfFile++;
+            clear();
+        } catch ( final FileNotFoundException exc ) {
+            throw new RuntimeException( "Could not create the log file.  Please make sure that directory that the log file should be placed in does exist." );
+        } catch ( final Throwable t ) {
+            t.printStackTrace( System.err );
+        } finally {
+            if( out != null ) { try { out.close(); } catch(Exception e) {} }
+        }
+    }
+
+    /**
+     * Clears all the events in the log.
+     */
+    public void clear() {
+        this.events.clear();
+    }
+
+    /**
+     * Sets the maximum number of log events that are allowed in memory.
+     * If this number is reached, all events are written to file.
+     * The default is 1000.
+     * 
+     * @param maxEventsInMemory The maximum number of events in memory.
+     */
+    public void setMaxEventsInMemory(final int maxEventsInMemory) {
+        this.maxEventsInMemory = maxEventsInMemory;
+    }
+
+    /**
+     * @see org.drools.audit.WorkingMemoryLogger
+     */
+    public void logEventCreated(final LogEvent logEvent) {
+        this.events.add( logEvent );
+        if ( this.events.size() > this.maxEventsInMemory ) {
+            writeToDisk();
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/WorkingMemoryInMemoryLogger.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/WorkingMemoryInMemoryLogger.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/WorkingMemoryInMemoryLogger.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,74 @@
+package org.drools.audit;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.ObjectOutputStream;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.WorkingMemory;
+import org.drools.audit.event.LogEvent;
+
+import com.thoughtworks.xstream.XStream;
+
+/**
+ * A logger of events generated by a working memory.
+ * It stores its information in memory, so it can be retrieved later.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen </a>
+ */
+public class WorkingMemoryInMemoryLogger extends WorkingMemoryLogger {
+
+    private final List events            = new ArrayList();
+
+    /**
+     * Creates a new WorkingMemoryInMemoryLogger for the given working memory.
+     * @param workingMemory
+     */
+    public WorkingMemoryInMemoryLogger(final WorkingMemory workingMemory) {
+        super( workingMemory );
+    }
+
+    public String getEvents() {
+        final XStream xstream = new XStream();
+        StringWriter writer = new StringWriter();
+        try {
+            final ObjectOutputStream out = xstream.createObjectOutputStream(writer);
+        	out.writeObject( this.events );
+            out.close();
+        } catch (Throwable t) {
+        	throw new RuntimeException("Unable to create event output: " + t.getMessage());
+        }
+        return writer.toString();
+    }
+
+    /**
+     * Clears all the events in the log.
+     */
+    public void clear() {
+        this.events.clear();
+    }
+
+    /**
+     * @see org.drools.audit.WorkingMemoryLogger
+     */
+    public void logEventCreated(final LogEvent logEvent) {
+        this.events.add( logEvent );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/WorkingMemoryLogger.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/WorkingMemoryLogger.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/WorkingMemoryLogger.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,481 @@
+package org.drools.audit;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.WorkingMemoryEventManager;
+import org.drools.FactHandle;
+import org.drools.WorkingMemory;
+import org.drools.audit.event.ActivationLogEvent;
+import org.drools.audit.event.ILogEventFilter;
+import org.drools.audit.event.LogEvent;
+import org.drools.audit.event.ObjectLogEvent;
+import org.drools.audit.event.RuleBaseLogEvent;
+import org.drools.audit.event.RuleFlowGroupLogEvent;
+import org.drools.audit.event.RuleFlowLogEvent;
+import org.drools.audit.event.RuleFlowNodeLogEvent;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.event.ActivationCancelledEvent;
+import org.drools.event.ActivationCreatedEvent;
+import org.drools.event.AfterActivationFiredEvent;
+import org.drools.event.AfterFunctionRemovedEvent;
+import org.drools.event.AfterPackageAddedEvent;
+import org.drools.event.AfterPackageRemovedEvent;
+import org.drools.event.AfterRuleAddedEvent;
+import org.drools.event.AfterRuleBaseLockedEvent;
+import org.drools.event.AfterRuleBaseUnlockedEvent;
+import org.drools.event.AfterRuleRemovedEvent;
+import org.drools.event.AgendaEventListener;
+import org.drools.event.AgendaGroupPoppedEvent;
+import org.drools.event.AgendaGroupPushedEvent;
+import org.drools.event.BeforeActivationFiredEvent;
+import org.drools.event.BeforeFunctionRemovedEvent;
+import org.drools.event.BeforePackageAddedEvent;
+import org.drools.event.BeforePackageRemovedEvent;
+import org.drools.event.BeforeRuleAddedEvent;
+import org.drools.event.BeforeRuleBaseLockedEvent;
+import org.drools.event.BeforeRuleBaseUnlockedEvent;
+import org.drools.event.BeforeRuleRemovedEvent;
+import org.drools.event.ObjectInsertedEvent;
+import org.drools.event.ObjectUpdatedEvent;
+import org.drools.event.ObjectRetractedEvent;
+import org.drools.event.RuleBaseEventListener;
+import org.drools.event.RuleFlowCompletedEvent;
+import org.drools.event.RuleFlowEventListener;
+import org.drools.event.RuleFlowGroupActivatedEvent;
+import org.drools.event.RuleFlowGroupDeactivatedEvent;
+import org.drools.event.RuleFlowNodeTriggeredEvent;
+import org.drools.event.RuleFlowStartedEvent;
+import org.drools.event.WorkingMemoryEventListener;
+import org.drools.rule.Declaration;
+import org.drools.spi.Activation;
+import org.drools.spi.Tuple;
+
+/**
+ * A logger of events generated by a working memory.
+ * It listens to the events generated by the working memory and
+ * creates associated log event (containing a snapshot of the
+ * state of the working event at that time).
+ * 
+ * Filters can be used to filter out unwanted events.
+ * 
+ * Subclasses of this class should implement the logEventCreated(LogEvent)
+ * method and store this information, like for example log to file
+ * or database.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen </a>
+ */
+public abstract class WorkingMemoryLogger
+    implements
+    WorkingMemoryEventListener,
+    AgendaEventListener,
+    RuleFlowEventListener,
+    RuleBaseEventListener {
+
+    private final List    filters = new ArrayList();
+
+    /**
+     * Creates a new working memory logger for the given working memory.
+     * 
+     * @param workingMemory
+     */
+    public WorkingMemoryLogger(final WorkingMemoryEventManager workingMemoryEventManager) {
+        workingMemoryEventManager.addEventListener( (WorkingMemoryEventListener) this );
+        workingMemoryEventManager.addEventListener( (AgendaEventListener) this );
+        workingMemoryEventManager.addEventListener( (RuleFlowEventListener) this );
+        workingMemoryEventManager.addEventListener( (RuleBaseEventListener) this );
+    }
+
+    /**
+     * This method is invoked every time a new log event is created.
+     * Subclasses should implement this method and store the event,
+     * like for example log to a file or database.
+     * 
+     * @param logEvent
+     */
+    public abstract void logEventCreated(LogEvent logEvent);
+
+    /**
+     * This method is invoked every time a new log event is created.
+     * It filters out unwanted events.
+     * 
+     * @param logEvent
+     */
+    private void filterLogEvent(final LogEvent logEvent) {
+        final Iterator iterator = this.filters.iterator();
+        while ( iterator.hasNext() ) {
+            final ILogEventFilter filter = (ILogEventFilter) iterator.next();
+            // do nothing if one of the filters doesn't accept the event
+            if ( !filter.acceptEvent( logEvent ) ) {
+                return;
+            }
+        }
+        // if all the filters accepted the event, signal the creation
+        // of the event
+        logEventCreated( logEvent );
+    }
+
+    /**
+     * Adds the given filter to the list of filters for this event log.
+     * A log event must be accepted by all the filters to be entered in
+     * the event log.
+     *
+     * @param filter The filter that should be added.
+     */
+    public void addFilter(final ILogEventFilter filter) {
+        if ( filter == null ) {
+            throw new NullPointerException();
+        }
+        this.filters.add( filter );
+    }
+
+    /**
+     * Removes the given filter from the list of filters for this event log.
+     * If the given filter was not a filter of this event log, nothing
+     * happens.
+     *
+     * @param filter The filter that should be removed.
+     */
+    public void removeFilter(final ILogEventFilter filter) {
+        this.filters.remove( filter );
+    }
+
+    /**
+     * Clears all filters of this event log.
+     */
+    public void clearFilters() {
+        this.filters.clear();
+    }
+
+    /**
+     * @see org.drools.event.WorkingMemoryEventListener
+     */
+    public void objectInserted(final ObjectInsertedEvent event) {
+        filterLogEvent( new ObjectLogEvent( LogEvent.INSERTED,
+                                            ((InternalFactHandle) event.getFactHandle()).getId(),
+                                            event.getObject().toString() ) );
+    }
+
+    /**
+     * @see org.drools.event.WorkingMemoryEventListener
+     */
+    public void objectUpdated(final ObjectUpdatedEvent event) {
+        filterLogEvent( new ObjectLogEvent( LogEvent.UPDATED,
+                                            ((InternalFactHandle) event.getFactHandle()).getId(),
+                                            event.getObject().toString() ) );
+    }
+
+    /**
+     * @see org.drools.event.WorkingMemoryEventListener
+     */
+    public void objectRetracted(final ObjectRetractedEvent event) {
+        filterLogEvent( new ObjectLogEvent( LogEvent.RETRACTED,
+                                            ((InternalFactHandle) event.getFactHandle()).getId(),
+                                            event.getOldObject().toString() ) );
+    }
+
+    /**
+     * @see org.drools.event.AgendaEventListener
+     */
+    public void activationCreated(final ActivationCreatedEvent event,
+                                  final WorkingMemory workingMemory) {
+        filterLogEvent( new ActivationLogEvent( LogEvent.ACTIVATION_CREATED,
+                                                getActivationId( event.getActivation() ),
+                                                event.getActivation().getRule().getName(),
+                                                extractDeclarations( event.getActivation(), workingMemory ),
+    											event.getActivation().getRule().getRuleFlowGroup() ) );
+	}
+
+    /**
+     * @see org.drools.event.AgendaEventListener
+     */
+    public void activationCancelled(final ActivationCancelledEvent event,
+                                    final WorkingMemory workingMemory) {
+        filterLogEvent( new ActivationLogEvent( LogEvent.ACTIVATION_CANCELLED,
+                                                getActivationId( event.getActivation() ),
+                                                event.getActivation().getRule().getName(),
+                                                extractDeclarations( event.getActivation(), workingMemory ),
+    											event.getActivation().getRule().getRuleFlowGroup() ) );
+    }
+
+    /**
+     * @see org.drools.event.AgendaEventListener
+     */
+    public void beforeActivationFired(final BeforeActivationFiredEvent event,
+                                      final WorkingMemory workingMemory) {
+        filterLogEvent( new ActivationLogEvent( LogEvent.BEFORE_ACTIVATION_FIRE,
+                                                getActivationId( event.getActivation() ),
+                                                event.getActivation().getRule().getName(),
+                                                extractDeclarations( event.getActivation(), workingMemory ),
+    											event.getActivation().getRule().getRuleFlowGroup() ) );
+    }
+
+    /**
+     * @see org.drools.event.AgendaEventListener
+     */
+    public void afterActivationFired(final AfterActivationFiredEvent event,
+                                     final WorkingMemory workingMemory) {
+        filterLogEvent( new ActivationLogEvent( LogEvent.AFTER_ACTIVATION_FIRE,
+                                                getActivationId( event.getActivation() ),
+                                                event.getActivation().getRule().getName(),
+                                                extractDeclarations( event.getActivation(), workingMemory ),
+    											event.getActivation().getRule().getRuleFlowGroup() ) );
+    }
+
+    /**
+     * Creates a string representation of the declarations of an activation.
+     * This is a list of name-value-pairs for each of the declarations in the
+     * tuple of the activation.  The name is the identifier (=name) of the
+     * declaration, and the value is a toString of the value of the
+     * parameter, followed by the id of the fact between parentheses.
+     * 
+     * @param activation The activation from which the declarations should be extracted
+     * @return A String represetation of the declarations of the activation.
+     */
+    private String extractDeclarations(final Activation activation,  final WorkingMemory workingMemory) {
+        final StringBuffer result = new StringBuffer();
+        final Tuple tuple = activation.getTuple();
+        final Map declarations = activation.getSubRule().getOuterDeclarations();
+        for ( Iterator it = declarations.values().iterator(); it.hasNext(); ) {
+            final Declaration declaration = (Declaration) it.next();
+            final FactHandle handle = tuple.get( declaration );
+            if ( handle instanceof InternalFactHandle ) {
+                final InternalFactHandle handleImpl = (InternalFactHandle) handle;
+                if ( handleImpl.getId() == -1 ) {
+                    // This handle is now invalid, probably due to an fact retraction
+                    continue;
+                }
+                final Object value = declaration.getValue( (InternalWorkingMemory) workingMemory, workingMemory.getObject( handle ) );
+
+                result.append( declaration.getIdentifier() );
+                result.append( "=" );
+                if ( value == null ) {
+                    // this should never occur
+                    result.append( "null" );
+                } else {
+                    result.append( value );
+                    result.append( "(" );
+                    result.append( handleImpl.getId() );
+                    result.append( ")" );
+                }
+            }
+            if ( it.hasNext() ) {
+                result.append( "; " );
+            }
+        }
+        return result.toString();
+    }
+
+    /**
+     * Returns a String that can be used as unique identifier for an
+     * activation.  Since the activationId is the same for all assertions
+     * that are created during a single insert, update or retract, the
+     * key of the tuple of the activation is added too (which is a set
+     * of fact handle ids). 
+     * 
+     * @param activation The activation for which a unique id should be generated
+     * @return A unique id for the activation
+     */
+    private static String getActivationId(final Activation activation) {
+        final StringBuffer result = new StringBuffer( activation.getRule().getName() );
+        result.append( " [" );
+        final Tuple tuple = activation.getTuple();
+        final FactHandle[] handles = tuple.getFactHandles();
+        for ( int i = 0; i < handles.length; i++ ) {
+            result.append( ((InternalFactHandle) handles[i]).getId() );
+            if ( i < handles.length - 1 ) {
+                result.append( ", " );
+            }
+        }
+        return result.append( "]" ).toString();
+    }
+    
+    public void agendaGroupPopped(final AgendaGroupPoppedEvent event,
+                                  final WorkingMemory workingMemory) {
+        // we don't audit this yet     
+    }
+
+    public void agendaGroupPushed(final AgendaGroupPushedEvent event,
+                                  final WorkingMemory workingMemory) {
+        // we don't audit this yet        
+    }
+    
+    public void beforeRuleFlowStarted(RuleFlowStartedEvent event,
+            					      WorkingMemory workingMemory) {
+        filterLogEvent( new RuleFlowLogEvent( LogEvent.BEFORE_RULEFLOW_CREATED,
+        		event.getRuleFlowProcessInstance().getProcess().getId(),
+                event.getRuleFlowProcessInstance().getProcess().getName() ) );
+    }
+
+    public void afterRuleFlowStarted(RuleFlowStartedEvent event,
+                                     WorkingMemory workingMemory) {
+        filterLogEvent(new RuleFlowLogEvent(LogEvent.AFTER_RULEFLOW_CREATED,
+                event.getRuleFlowProcessInstance().getProcess().getId(),
+                event.getRuleFlowProcessInstance().getProcess().getName()));
+    }
+
+    public void beforeRuleFlowCompleted(RuleFlowCompletedEvent event,
+              					  WorkingMemory workingMemory) {
+        filterLogEvent( new RuleFlowLogEvent( LogEvent.BEFORE_RULEFLOW_COMPLETED,
+        		event.getRuleFlowProcessInstance().getProcess().getId(),
+                event.getRuleFlowProcessInstance().getProcess().getName() ) );
+    }
+    
+    public void afterRuleFlowCompleted(RuleFlowCompletedEvent event,
+                                       WorkingMemory workingMemory) {
+        filterLogEvent(new RuleFlowLogEvent(LogEvent.AFTER_RULEFLOW_COMPLETED,
+                event.getRuleFlowProcessInstance().getProcess().getId(),
+                event.getRuleFlowProcessInstance().getProcess().getName()));
+    }
+
+    public void beforeRuleFlowGroupActivated(
+            RuleFlowGroupActivatedEvent event,
+            WorkingMemory workingMemory) {
+        filterLogEvent(new RuleFlowGroupLogEvent(
+                LogEvent.BEFORE_RULEFLOW_GROUP_ACTIVATED, event
+                        .getRuleFlowGroup().getName(), event.getRuleFlowGroup()
+                        .size()));
+    }
+    
+    public void afterRuleFlowGroupActivated(
+            RuleFlowGroupActivatedEvent event,
+            WorkingMemory workingMemory) {
+        filterLogEvent(new RuleFlowGroupLogEvent(
+                LogEvent.AFTER_RULEFLOW_GROUP_ACTIVATED,
+                event.getRuleFlowGroup().getName(),
+                event.getRuleFlowGroup().size()));
+    }
+
+    public void beforeRuleFlowGroupDeactivated(
+            RuleFlowGroupDeactivatedEvent event, 
+            WorkingMemory workingMemory) {
+        filterLogEvent(new RuleFlowGroupLogEvent(
+                LogEvent.BEFORE_RULEFLOW_GROUP_DEACTIVATED,
+                event.getRuleFlowGroup().getName(),
+                event.getRuleFlowGroup().size()));
+    }
+    
+    public void afterRuleFlowGroupDeactivated(
+            RuleFlowGroupDeactivatedEvent event,
+            WorkingMemory workingMemory) {
+        filterLogEvent(new RuleFlowGroupLogEvent(
+                LogEvent.AFTER_RULEFLOW_GROUP_DEACTIVATED,
+                event.getRuleFlowGroup().getName(),
+                event.getRuleFlowGroup().size()));
+    }
+
+    public void beforeRuleFlowNodeTriggered(RuleFlowNodeTriggeredEvent event,
+                                            WorkingMemory workingMemory) {
+        filterLogEvent(new RuleFlowNodeLogEvent(LogEvent.BEFORE_RULEFLOW_NODE_TRIGGERED,
+                event.getRuleFlowNodeInstance().getId() + "",
+                event.getRuleFlowNodeInstance().getNode().getName(),
+                event.getRuleFlowProcessInstance().getProcess().getId(), event
+                        .getRuleFlowProcessInstance().getProcess().getName()));
+    }
+
+    public void afterRuleFlowNodeTriggered(RuleFlowNodeTriggeredEvent event,
+                                           WorkingMemory workingMemory) {
+        filterLogEvent(new RuleFlowNodeLogEvent(LogEvent.AFTER_RULEFLOW_NODE_TRIGGERED,
+                event.getRuleFlowNodeInstance().getId() + "",
+                event.getRuleFlowNodeInstance().getNode().getName(),
+                event.getRuleFlowProcessInstance().getProcess().getId(), event
+                        .getRuleFlowProcessInstance().getProcess().getName()));
+    }
+
+    public void afterPackageAdded(AfterPackageAddedEvent event) {
+        filterLogEvent( new RuleBaseLogEvent( LogEvent.AFTER_PACKAGE_ADDED,
+                                              event.getPackage().getName(),
+                                              null ) );
+    }
+
+    public void afterPackageRemoved(AfterPackageRemovedEvent event) {
+        filterLogEvent( new RuleBaseLogEvent( LogEvent.AFTER_PACKAGE_REMOVED,
+                                              event.getPackage().getName(),
+                                              null ) );
+    }
+
+    public void afterRuleAdded(AfterRuleAddedEvent event) {
+        filterLogEvent( new RuleBaseLogEvent( LogEvent.AFTER_RULE_ADDED,
+                                              event.getPackage().getName(),
+                                              event.getRule().getName() ) );
+    }
+
+    public void afterRuleRemoved(AfterRuleRemovedEvent event) {
+        filterLogEvent( new RuleBaseLogEvent( LogEvent.AFTER_RULE_REMOVED,
+                                              event.getPackage().getName(),
+                                              event.getRule().getName() ) );
+    }
+
+    public void beforePackageAdded(BeforePackageAddedEvent event) {
+        filterLogEvent( new RuleBaseLogEvent( LogEvent.BEFORE_PACKAGE_ADDED,
+                                              event.getPackage().getName(),
+                                              null ) );
+    }
+
+    public void beforePackageRemoved(BeforePackageRemovedEvent event) {
+        filterLogEvent( new RuleBaseLogEvent( LogEvent.BEFORE_PACKAGE_REMOVED,
+                                              event.getPackage().getName(),
+                                              null ) );
+    }
+
+    public void beforeRuleAdded(BeforeRuleAddedEvent event) {
+        filterLogEvent( new RuleBaseLogEvent( LogEvent.BEFORE_RULE_ADDED,
+                                              event.getPackage().getName(),
+                                              event.getRule().getName() ) );
+    }
+
+    public void beforeRuleRemoved(BeforeRuleRemovedEvent event) {
+        filterLogEvent( new RuleBaseLogEvent( LogEvent.BEFORE_RULE_REMOVED,
+                                              event.getPackage().getName(),
+                                              event.getRule().getName() ) );
+    }
+    
+    public void afterFunctionRemoved(AfterFunctionRemovedEvent event) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public void afterRuleBaseLocked(AfterRuleBaseLockedEvent event) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public void afterRuleBaseUnlocked(AfterRuleBaseUnlockedEvent event) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public void beforeFunctionRemoved(BeforeFunctionRemovedEvent event) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public void beforeRuleBaseLocked(BeforeRuleBaseLockedEvent event) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public void beforeRuleBaseUnlocked(BeforeRuleBaseUnlockedEvent event) {
+        // TODO Auto-generated method stub
+        
+    }        
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/ActivationLogEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/ActivationLogEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/ActivationLogEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,118 @@
+package org.drools.audit.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * An activation event logged by the WorkingMemoryLogger.
+ * It is a snapshot of the event as it was thrown by the working memory.
+ * It contains the activation id, the name of the rule and a String
+ * representing the declarations of the activation, which is a list of
+ * name-value-pairs for each of the declarations in the tuple of the
+ * activation.  The name is the identifier (=name) of the
+ * declaration, and the value is a toString of the value of the
+ * parameter, followed by the id of the fact between parentheses.
+ * e.g. param1=10; param2=Person[John Doe]
+ * 
+ * Such a String representation is used to create a snapshot of the
+ * current state of the activation by storing a toString of the facts
+ * bound in the activation.  If necessary, this event could be extended
+ * to contain a map of declarations too.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen </a>
+ */
+public class ActivationLogEvent extends LogEvent {
+
+    private String activationId;
+    private String rule;
+    private String declarations;
+    private String ruleFlowGroup;
+
+    /**
+     * Create a new activation log event.
+     * 
+     * @param type The type of event.  This can only be ACTIVATION_CREATED, ACTIVATION_CANCELLED,
+     * BEFORE_ACTIVATION_FIRE or AFTER_ACTIVATION_FIRE.
+     * @param activationId The id of the activation
+     * @param rule The name of the rule of the activation
+     * @param declarations A String representation of the declarations in the
+     * activation.
+     */
+    public ActivationLogEvent(final int type,
+                              final String activationId,
+                              final String rule,
+                              final String declarations,
+                              final String ruleFlowGroup) {
+        super( type );
+        this.activationId = activationId;
+        this.rule = rule;
+        this.declarations = declarations;
+        this.ruleFlowGroup = ruleFlowGroup;
+    }
+
+    /**
+     * Returns a unique id for the activation.
+     * 
+     * @return The id of the activation
+     */
+    public String getActivationId() {
+        return this.activationId;
+    }
+
+    /**
+     * Returns the name of the rule of the activation.
+     * 
+     * @return The name of the rule
+     */
+    public String getRule() {
+        return this.rule;
+    }
+
+    /**
+     * Returns a String representation of the declarations in the
+     * activation.
+     * 
+     * @return A String representation of the declarations.
+     */
+    public String getDeclarations() {
+        return this.declarations;
+    }
+    
+    public String getRuleFlowGroup() {
+    	return ruleFlowGroup;
+    }
+
+    public String toString() {
+
+        String msg = null;
+        switch ( this.getType() ) {
+            case ACTIVATION_CANCELLED :
+                msg = "ACTIVATION CANCELLED";
+                break;
+            case ACTIVATION_CREATED :
+                msg = "ACTIVATION CREATED";
+                break;
+
+            case AFTER_ACTIVATION_FIRE :
+                msg = "AFTER ACTIVATION FIRED";
+                break;
+            case BEFORE_ACTIVATION_FIRE :
+                msg = "BEFORE ACTIVATION FIRED";
+                break;
+        }
+        return msg + " rule:" + this.rule + " activationId:" + this.activationId + " declarations: " + this.declarations + (ruleFlowGroup == null ? "" : " ruleflow-group: " + ruleFlowGroup);
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/ActivationLogEventFilter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/ActivationLogEventFilter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/ActivationLogEventFilter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,79 @@
+package org.drools.audit.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * An event filter that can be used to filter assertion events.
+ * By default, all events are allowed.  You can filter out any of the
+ * four types of assertion events by setting the allow boolean
+ * for that type to false.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen </a>
+ */
+public class ActivationLogEventFilter
+    implements
+    ILogEventFilter {
+
+    private boolean allowActivationCreatedEvents    = true;
+    private boolean allowActivationCancelledEvents  = true;
+    private boolean allowBeforeActivationFireEvents = true;
+    private boolean allowAfterActivationFireEvents  = true;
+
+    public ActivationLogEventFilter(final boolean allowActivationCreatedEvents,
+                                    final boolean allowActivationCancelledEvents,
+                                    final boolean allowBeforeActivationFireEvents,
+                                    final boolean allowAfterActivationFireEvents) {
+        setAllowActivationCreatedEvents( allowActivationCreatedEvents );
+        setAllowActivationCancelledEvents( allowActivationCancelledEvents );
+        setAllowBeforeActivationFireEvents( allowBeforeActivationFireEvents );
+        setAllowAfterActivationFireEvents( allowAfterActivationFireEvents );
+    }
+
+    /**
+     * @see org.drools.audit.event.ILogEventFilter
+     */
+    public boolean acceptEvent(final LogEvent event) {
+        switch ( event.getType() ) {
+            case LogEvent.ACTIVATION_CREATED :
+                return this.allowActivationCreatedEvents;
+            case LogEvent.ACTIVATION_CANCELLED :
+                return this.allowActivationCancelledEvents;
+            case LogEvent.BEFORE_ACTIVATION_FIRE :
+                return this.allowBeforeActivationFireEvents;
+            case LogEvent.AFTER_ACTIVATION_FIRE :
+                return this.allowAfterActivationFireEvents;
+            default :
+                return true;
+        }
+    }
+
+    public void setAllowActivationCreatedEvents(final boolean allowActivationCreatedEvents) {
+        this.allowActivationCreatedEvents = allowActivationCreatedEvents;
+    }
+
+    public void setAllowActivationCancelledEvents(final boolean allowActivationCancelledEvents) {
+        this.allowActivationCancelledEvents = allowActivationCancelledEvents;
+    }
+
+    public void setAllowBeforeActivationFireEvents(final boolean allowBeforeActivationFireEvents) {
+        this.allowBeforeActivationFireEvents = allowBeforeActivationFireEvents;
+    }
+
+    public void setAllowAfterActivationFireEvents(final boolean allowAfterActivationFireEvents) {
+        this.allowAfterActivationFireEvents = allowAfterActivationFireEvents;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/ILogEventFilter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/ILogEventFilter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/ILogEventFilter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,33 @@
+package org.drools.audit.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * An event filter that can be used to filter log events.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen </a>
+ */
+public interface ILogEventFilter {
+
+    /**
+     * Returns whether the given event should be filtered from the event log or not.
+     * @param event The log event
+     * @return Whether the event should be filtered from the event log or not.
+     */
+    boolean acceptEvent(LogEvent event);
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/LogEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/LogEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/LogEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,84 @@
+package org.drools.audit.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * An event logged by the WorkingMemoryLogger.
+ * It is a snapshot of the event as it was thrown by the working memory.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen </a>
+ */
+public class LogEvent {
+
+public static final int INSERTED                                = 1;
+    public static final int UPDATED                             = 2;
+    public static final int RETRACTED                           = 3;
+
+    public static final int ACTIVATION_CREATED                  = 4;
+    public static final int ACTIVATION_CANCELLED                = 5;
+    public static final int BEFORE_ACTIVATION_FIRE              = 6;
+    public static final int AFTER_ACTIVATION_FIRE               = 7;
+
+    public static final int BEFORE_RULEFLOW_CREATED             = 8;
+    public static final int AFTER_RULEFLOW_CREATED              = 9;
+    public static final int BEFORE_RULEFLOW_COMPLETED           = 10;
+    public static final int AFTER_RULEFLOW_COMPLETED            = 11;
+    public static final int BEFORE_RULEFLOW_GROUP_ACTIVATED     = 12;
+    public static final int AFTER_RULEFLOW_GROUP_ACTIVATED      = 13;
+    public static final int BEFORE_RULEFLOW_GROUP_DEACTIVATED   = 14;
+    public static final int AFTER_RULEFLOW_GROUP_DEACTIVATED    = 15;
+
+    public static final int BEFORE_PACKAGE_ADDED                = 16;
+    public static final int AFTER_PACKAGE_ADDED                 = 17;
+    public static final int BEFORE_PACKAGE_REMOVED              = 18;
+    public static final int AFTER_PACKAGE_REMOVED               = 19;
+    public static final int BEFORE_RULE_ADDED                   = 20;
+    public static final int AFTER_RULE_ADDED                    = 21;
+    public static final int BEFORE_RULE_REMOVED                 = 22;
+    public static final int AFTER_RULE_REMOVED                  = 23;
+
+    public static final int BEFORE_RULEFLOW_NODE_TRIGGERED      = 24;
+    public static final int AFTER_RULEFLOW_NODE_TRIGGERED       = 25;
+    public static final int BEFORE_RULEFLOW_NODE_EXITED         = 26;
+    public static final int AFTER_RULEFLOW_NODE_EXITED          = 27;
+    
+    public static final int BEFORE_TASK_INSTANCE_CREATED        = 28;
+    public static final int AFTER_TASK_INSTANCE_CREATED         = 29;
+    public static final int BEFORE_TASK_INSTANCE_COMPLETED      = 30;
+    public static final int AFTER_TASK_INSTANCE_COMPLETED       = 31;
+    
+    private int             type;
+
+    /**
+     * Creates a new log event.
+     * 
+     * @param type The type of the log event.
+     */
+    public LogEvent(final int type) {
+        this.type = type;
+    }
+
+    /**
+     * Returns the type of the log event as defined in this class.
+     * 
+     * @return The type of the log event.
+     */
+    public int getType() {
+        return this.type;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/ObjectLogEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/ObjectLogEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/ObjectLogEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,84 @@
+package org.drools.audit.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * An object event logged by the WorkingMemoryLogger.
+ * It is a snapshot of the event as it was thrown by the working memory.
+ * It contains the fact id and a String represention of the object
+ * at the time the event was logged.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen </a>
+ */
+public class ObjectLogEvent extends LogEvent {
+
+    private long   factId;
+    private String objectToString;
+
+    /**
+     * Create a new activation log event.
+     * 
+     * @param type The type of event.  This can only be LogEvent.OBJECT_ASSERTED,
+     * LogEvent.OBJECT_MODIFIED or LogEvent.OBJECT_RETRACTED.
+     * @param factId The id of the fact
+     * @param objectToString A toString of the fact 
+     */
+    public ObjectLogEvent(final int type,
+                          final long factId,
+                          final String objectToString) {
+        super( type );
+        this.factId = factId;
+        this.objectToString = objectToString;
+    }
+
+    /**
+     * Returns the fact id of the object this event is about.
+     * 
+     * @return the id of the fact
+     */
+    public long getFactId() {
+        return this.factId;
+    }
+
+    /**
+     * Returns a toString of the fact this event is about at the
+     * time the event was created.
+     * 
+     * @return the toString of the fact
+     */
+    public String getObjectToString() {
+        return this.objectToString;
+    }
+
+    public String toString() {
+        String msg = null;
+        switch ( this.getType() ) {
+            case INSERTED :
+                msg = "OBJECT ASSERTED";
+                break;
+            case UPDATED :
+                msg = "OBJECT MODIFIED";
+                break;
+
+            case RETRACTED :
+                msg = "OBJECT RETRACTED";
+                break;
+        }
+        return msg + " value:" + this.objectToString + " factId: " + this.factId;
+
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/RuleBaseLogEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/RuleBaseLogEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/RuleBaseLogEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,98 @@
+package org.drools.audit.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * A rulebase event logged by the WorkingMemoryLogger.
+ * It is a snapshot of the event as it was thrown by the rulebase.
+ * 
+ * @author etirelli
+ */
+public class RuleBaseLogEvent extends LogEvent {
+
+    private final String packageName;
+    private final String ruleName;
+
+    /**
+     * Create a new activation log event.
+     * 
+     * @param type The type of event.  
+     * @param packageName The name of the package
+     * @param ruleName The name of the rule 
+     */
+    public RuleBaseLogEvent(final int type,
+                            final String packageName,
+                            final String ruleName) {
+        super( type );
+        this.packageName = packageName;
+        this.ruleName = ruleName;
+    }
+
+    /**
+     * Returns the Package Name
+     * 
+     * @return The name of the package
+     */
+    public String getPackageName() {
+        return this.packageName;
+    }
+
+    /**
+     * Returns the name of the rule 
+     * 
+     * @return The name of the rule
+     */
+    public String getRuleName() {
+        return this.ruleName;
+    }
+
+    public String toString() {
+
+        String msg = null;
+        switch ( this.getType() ) {
+            case BEFORE_PACKAGE_ADDED :
+                msg = "BEFORE PACKAGE ADDED";
+                break;
+            case AFTER_PACKAGE_ADDED :
+                msg = "AFTER PACKAGE ADDED";
+                break;
+            case BEFORE_PACKAGE_REMOVED :
+                msg = "BEFORE PACKAGE REMOVED";
+                break;
+            case AFTER_PACKAGE_REMOVED :
+                msg = "AFTER PACKAGE REMOVED";
+                break;
+            case BEFORE_RULE_ADDED :
+                msg = "BEFORE RULE ADDED";
+                break;
+            case AFTER_RULE_ADDED :
+                msg = "AFTER RULE ADDED";
+                break;
+            case BEFORE_RULE_REMOVED :
+                msg = "BEFORE RULE REMOVED";
+                break;
+            case AFTER_RULE_REMOVED :
+                msg = "AFTER RULE REMOVED";
+                break;
+        }
+        String ruleMsg = "";
+        if( this.ruleName != null ) {
+            ruleMsg = " rule: \""+this.ruleName+"\"";
+        }
+        return msg + " package: \"" + this.packageName + "\""+ruleMsg;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/RuleFlowGroupLogEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/RuleFlowGroupLogEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/RuleFlowGroupLogEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,73 @@
+package org.drools.audit.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * A ruleflow-group event logged by the WorkingMemoryLogger.
+ * It is a snapshot of the event as it was thrown by the working memory.
+ * It contains the ruleflow group name and its size.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen </a>
+ */
+public class RuleFlowGroupLogEvent extends LogEvent {
+
+    private String groupName;
+    private int size;
+
+    /**
+     * Create a new ruleflow group log event.
+     * 
+     * @param type The type of event.  This can only be RULEFLOW_GROUP_ACTIVATED or RULEFLOW_GROUP_DEACTIVATED.
+     * @param groupName The name of the ruleflow group
+     * @param size The size of the ruleflow group
+     */
+    public RuleFlowGroupLogEvent(final int type,
+                                 final String groupName,
+                                 final int size) {
+        super( type );
+        this.groupName = groupName;
+        this.size = size;
+    }
+
+    public String getGroupName() {
+        return this.groupName;
+    }
+
+    public int getSize() {
+        return this.size;
+    }
+
+    public String toString() {
+
+        String msg = null;
+        switch ( this.getType() ) {
+            case BEFORE_RULEFLOW_GROUP_ACTIVATED :
+                msg = "BEFORE RULEFLOW GROUP ACTIVATED";
+                break;
+            case AFTER_RULEFLOW_GROUP_ACTIVATED :
+                msg = "AFTER RULEFLOW GROUP ACTIVATED";
+                break;
+            case BEFORE_RULEFLOW_GROUP_DEACTIVATED :
+                msg = "BEFORE RULEFLOW GROUP DEACTIVATED";
+                break;
+            case AFTER_RULEFLOW_GROUP_DEACTIVATED :
+                msg = "AFTER RULEFLOW GROUP DEACTIVATED";
+                break;
+        }
+        return msg + " group:" + this.groupName + "[size=" + this.size + "]";
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/RuleFlowLogEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/RuleFlowLogEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/RuleFlowLogEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,73 @@
+package org.drools.audit.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * A ruleflow event logged by the WorkingMemoryLogger.
+ * It is a snapshot of the event as it was thrown by the working memory.
+ * It contains the process name and id.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen </a>
+ */
+public class RuleFlowLogEvent extends LogEvent {
+
+    private String processId;
+    private String processName;
+
+    /**
+     * Create a new ruleflow log event.
+     * 
+     * @param type The type of event.  This can only be RULEFLOW_CREATED,
+     *        RULEFLOW_COMPLETED, RULEFLOW_NODE_START or RULEFLOW_NODE_END.
+     * @param processId The id of the process
+     * @param processName The name of the process
+     */
+    public RuleFlowLogEvent(final int type,
+                            final String processId,
+                            final String processName) {
+        super( type );
+        this.processId = processId;
+        this.processName = processName;
+    }
+
+    public String getProcessId() {
+        return this.processId;
+    }
+
+    public String getProcessName() {
+        return this.processName;
+    }
+
+    public String toString() {
+        String msg = null;
+        switch ( this.getType() ) {
+            case BEFORE_RULEFLOW_CREATED :
+                msg = "BEFORE RULEFLOW STARTED";
+                break;
+            case AFTER_RULEFLOW_CREATED :
+                msg = "AFTER RULEFLOW STARTED";
+                break;
+            case BEFORE_RULEFLOW_COMPLETED :
+                msg = "BEFORE RULEFLOW COMPLETED";
+                break;
+            case AFTER_RULEFLOW_COMPLETED :
+                msg = "AFTER RULEFLOW COMPLETED";
+                break;
+        }
+        return msg + " process:" + this.processName + "[id=" + this.processId + "]";
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/RuleFlowNodeLogEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/RuleFlowNodeLogEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/RuleFlowNodeLogEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,48 @@
+package org.drools.audit.event;
+
+public class RuleFlowNodeLogEvent extends RuleFlowLogEvent {
+    
+    private String nodeId;
+    private String nodeName;
+
+    /**
+     * Create a new ruleflow node log event.
+     * 
+     * @param type The type of event.  This can only be RULEFLOW_NODE_START or RULEFLOW_NODE_END.
+     * @param processId The id of the process
+     * @param processName The name of the process
+     */
+    public RuleFlowNodeLogEvent(final int type,
+                                final String nodeId,
+                                final String nodeName,
+                                final String processId,
+                                final String processName) {
+        super( type, processId, processName );
+        this.nodeId = nodeId;
+        this.nodeName = nodeName;
+    }
+    
+    public String getNodeId() {
+        return nodeId;
+    }
+    
+    public String getNodeName() {
+        return nodeName;
+    }
+    
+    public String toString() {
+        String msg = null;
+        switch ( this.getType() ) {
+            case BEFORE_RULEFLOW_NODE_TRIGGERED :
+                msg = "BEFORE RULEFLOW NODE TRIGGERED";
+                break;
+            case AFTER_RULEFLOW_NODE_TRIGGERED :
+                msg = "AFTER RULEFLOW NODE TRIGGERED";
+                break;
+            default:
+                return super.toString();
+        }
+        return msg + " node:" + nodeName + "[id=" + nodeId + "] process:" + getProcessName() + "[id=" + getProcessId() + "]";
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/WorkingMemoryLogEventFilter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/WorkingMemoryLogEventFilter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/audit/event/WorkingMemoryLogEventFilter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,70 @@
+package org.drools.audit.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * An event filter that can be used to filter working memory events.
+ * By default, all events are allowed.  You can filter out any of the
+ * three types of working memory events by setting the allow boolean
+ * for that type to false.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen </a>
+ */
+public class WorkingMemoryLogEventFilter
+    implements
+    ILogEventFilter {
+
+    private boolean allowInsertEvents  = true;
+    private boolean allowUpdateEvents  = true;
+    private boolean allowRetractEvents = true;
+
+    public WorkingMemoryLogEventFilter(final boolean allowAssertEvents,
+                                       final boolean allowModifyEvents,
+                                       final boolean allowRetractEvents) {
+        setAllowInsertEvents( allowAssertEvents );
+        setAllowUpdateEvents( allowModifyEvents );
+        setAllowRetractEvents( allowRetractEvents );
+    }
+
+    /**
+     * @see org.drools.audit.event.ILogEventFilter
+     */
+    public boolean acceptEvent(final LogEvent event) {
+        switch ( event.getType() ) {
+            case LogEvent.INSERTED :
+                return this.allowInsertEvents;
+            case LogEvent.UPDATED :
+                return this.allowUpdateEvents;
+            case LogEvent.RETRACTED :
+                return this.allowRetractEvents;
+            default :
+                return true;
+        }
+    }
+
+    public void setAllowInsertEvents(final boolean allowInsertEvents) {
+        this.allowInsertEvents = allowInsertEvents;
+    }
+
+    public void setAllowUpdateEvents(final boolean allowUpdateEvents) {
+        this.allowUpdateEvents = allowUpdateEvents;
+    }
+
+    public void setAllowRetractEvents(final boolean allowRetractEvents) {
+        this.allowRetractEvents = allowRetractEvents;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/AsyncFireAllRulesRuleBaseUpdateListener.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/AsyncFireAllRulesRuleBaseUpdateListener.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/AsyncFireAllRulesRuleBaseUpdateListener.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,29 @@
+/**
+ * 
+ */
+package org.drools.base;
+
+import org.drools.StatefulSession;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.event.BeforeRuleBaseUnlockedEvent;
+import org.drools.event.DefaultRuleBaseEventListener;
+import org.drools.spi.RuleBaseUpdateListener;
+
+public class AsyncFireAllRulesRuleBaseUpdateListener extends DefaultRuleBaseEventListener 
+implements RuleBaseUpdateListener {
+    private StatefulSession session;
+    
+    public AsyncFireAllRulesRuleBaseUpdateListener() {
+        
+    }
+    
+    public void setSession(StatefulSession session) {
+        this.session = (StatefulSession) session;
+    }
+    
+    public void beforeRuleBaseUnlocked(BeforeRuleBaseUnlockedEvent event) {
+        if ( session.getRuleBase().getAdditionsSinceLock() > 0 ) { 
+            session.asyncFireAllRules();
+        }
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/BaseClassFieldExtractor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/BaseClassFieldExtractor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/BaseClassFieldExtractor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,109 @@
+package org.drools.base;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.RuntimeDroolsException;
+import org.drools.spi.FieldExtractor;
+import org.drools.util.ClassUtils;
+import org.drools.util.asm.ClassFieldInspector;
+
+/**
+ * This is the supertype for the ASM generated classes for accessing a field.
+ * @author Alexander Bagerman
+ */
+abstract public class BaseClassFieldExtractor
+    implements
+    FieldExtractor {
+    private final int       index;
+
+    private final Class     fieldType;
+
+    private final ValueType valueType;
+
+    /**
+     * This constructor is not supposed to be used from outside the class hirarchy
+     * 
+     * @param index
+     * @param fieldType
+     * @param valueType
+     */
+    protected BaseClassFieldExtractor(final int index,
+                                      final Class fieldType,
+                                      final ValueType valueType) {
+        this.index = index;
+        this.fieldType = fieldType;
+        this.valueType = valueType;
+    }
+
+    /**
+     * This is the constructor to be used
+     * 
+     * @param clazz
+     * @param fieldName
+     */
+    public BaseClassFieldExtractor(final Class clazz,
+                                   final String fieldName) {
+        try {
+            final ClassFieldInspector inspector = new ClassFieldInspector( clazz );
+            this.index = ((Integer) inspector.getFieldNames().get( fieldName )).intValue();
+            this.fieldType = (Class) inspector.getFieldTypes().get( fieldName );
+            this.valueType = ValueType.determineValueType( this.fieldType );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( e );
+        }
+    }
+
+    public int getIndex() {
+        return this.index;
+    }
+
+    public Class getExtractToClass() {
+        return this.fieldType;
+    }
+
+    public String getExtractToClassName() {
+        return ClassUtils.canonicalName( this.fieldType );
+    }
+
+    public ValueType getValueType() {
+        return this.valueType;
+    }
+    
+    public boolean isGlobal() {
+        return false;
+    }
+    
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + this.fieldType.hashCode();
+        result = PRIME * result + this.index;
+        result = PRIME * result + this.valueType.hashCode();
+        return result;
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+        if ( !(object instanceof BaseClassFieldExtractor) ) {
+            return false;
+        }
+        final BaseClassFieldExtractor other = (BaseClassFieldExtractor) object;
+        return this.fieldType == other.fieldType && this.index == other.index && this.valueType.equals( other.valueType );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/BaseDuration.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/BaseDuration.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/BaseDuration.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,66 @@
+package org.drools.base;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.rule.Rule;
+import org.drools.spi.Duration;
+import org.drools.spi.Tuple;
+
+/**
+ * Implementation of the <code>Duration</code> interface
+ * for specifying truthness duration.
+ */
+public class BaseDuration
+    implements
+    Duration {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    /** The number of seconds of the duration. */
+    private long              seconds;
+
+    private Rule              rule;
+
+    /**
+     * Constructor.
+     * 
+     * @param seconds the number of seconds of the duration
+     */
+    public BaseDuration(final Rule rule,
+                        final long seconds) {
+        this.rule = rule;
+        this.seconds = seconds;
+    }
+
+    /**
+     * Retrieves the duration for which the conditions of this
+     * <code>Tuple</code> must remain true before the rule will fire.
+     * 
+     * @param tuple the <code>Tuple</code>
+     * 
+     * @return the duration in seconds
+     */
+    public long getDuration(final Tuple tuple) {
+        return this.seconds;
+    }
+
+    public Rule getRule() {
+        return this.rule;
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/BaseEvaluator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/BaseEvaluator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/BaseEvaluator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,75 @@
+package org.drools.base;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.base.evaluators.Operator;
+import org.drools.common.InternalFactHandle;
+import org.drools.spi.Evaluator;
+
+/**
+ * BaseEvaluator is an Object Comparator that is operator aware
+ * 
+ * @author mproctor
+ * 
+ */
+public abstract class BaseEvaluator
+    implements
+    Evaluator {
+
+    private final Operator  operator;
+
+    private final ValueType type;
+
+    public BaseEvaluator(final ValueType type,
+                         final Operator operator) {
+        this.type = type;
+        this.operator = operator;
+    }
+
+    public Operator getOperator() {
+        return this.operator;
+    }
+
+    public ValueType getValueType() {
+        return this.type;
+    }
+
+    public ValueType getCoercedValueType() {
+        return this.type;
+    }
+
+    public Object prepareObject(InternalFactHandle handle) {
+        return handle.getObject();
+    }
+    
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+        if ( object == null || !(object instanceof BaseEvaluator) ) {
+            return false;
+        }
+
+        final Evaluator other = (Evaluator) object;
+        return this.getOperator() == other.getOperator() && this.getValueType() == other.getValueType();
+    }
+
+    public int hashCode() {
+        return (this.getValueType().hashCode()) ^ (this.getOperator().hashCode()) ^ (this.getClass().hashCode());
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassFieldExtractor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassFieldExtractor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassFieldExtractor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,232 @@
+package org.drools.base;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.lang.reflect.Method;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.common.DroolsObjectInputStream;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.FieldExtractor;
+import org.drools.util.ClassUtils;
+
+/**
+ * This provides access to fields, and what their numerical index/object type is.
+ * This is basically a wrapper class around dynamically generated subclasses of 
+ * BaseClassFieldExtractor,
+ *  which allows serialization by regenerating the accessor classes 
+ * when needed.
+ * 
+ * @author Michael Neale
+ */
+public class ClassFieldExtractor
+    implements
+    FieldExtractor {
+    /**
+     * 
+     */
+    private static final long        serialVersionUID = 400L;
+    private String                   fieldName;
+    private Class                    clazz;
+    private transient FieldExtractor extractor;
+
+    public ClassFieldExtractor(final Class clazz,
+                               final String fieldName) {
+        this( clazz,
+              fieldName,
+              clazz.getClassLoader() );
+    }
+
+    public ClassFieldExtractor(final Class clazz,
+                               final String fieldName,
+                               final ClassLoader classLoader) {
+        this( clazz,
+              fieldName,
+              classLoader == null ? clazz.getClassLoader() : classLoader,
+              new ClassFieldExtractorFactory() );
+    }
+
+    public ClassFieldExtractor(final Class clazz,
+                               final String fieldName,
+                               final ClassLoader classLoader,
+                               final ClassFieldExtractorFactory factory) {
+        this.clazz = clazz;
+        this.fieldName = fieldName;
+        init( classLoader,
+              factory );
+    }
+
+    private void writeObject(ObjectOutputStream s) throws IOException {
+        // Call even if there is no default serializable fields.
+        s.defaultWriteObject();
+    }
+
+    private void readObject(final ObjectInputStream is) throws ClassNotFoundException,
+                                                       IOException,
+                                                       Exception {
+        //always perform the default de-serialization first
+        is.defaultReadObject();
+        if ( is instanceof DroolsObjectInputStream ) {
+            DroolsObjectInputStream dois = (DroolsObjectInputStream) is;
+            this.extractor = dois.getExtractorFactory().getExtractor( this.clazz,
+                                                                      this.fieldName,
+                                                                      dois.getClassLoader() );
+        } else {
+            this.extractor = ClassFieldExtractorCache.getInstance().getExtractor( this.clazz,
+                                                                                  this.fieldName,
+                                                                                  this.clazz.getClassLoader() );
+
+        }
+    }
+
+//    private Object readResolve() {
+//        // always return the value from the cache
+//        return ClassFieldExtractorCache.getInstance().getExtractor( this.clazz,
+//                                                                    this.fieldName,
+//                                                                    this.clazz.getClassLoader() );
+//    }
+
+    private void init(final ClassLoader classLoader,
+                      final ClassFieldExtractorFactory factory) {
+        try {
+            this.extractor = factory.getClassFieldExtractor( this.clazz,
+                                                             this.fieldName,
+                                                             classLoader );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( e );
+        }
+    }
+
+    public int getIndex() {
+        return this.extractor.getIndex();
+    }
+
+    public String getFieldName() {
+        return this.fieldName;
+    }
+
+    public Object getValue(InternalWorkingMemory workingMemory,
+                           final Object object) {
+        return this.extractor.getValue( workingMemory,
+                                        object );
+    }
+
+    public ValueType getValueType() {
+        return this.extractor.getValueType();
+    }
+
+    public Class getExtractToClass() {
+        return this.extractor.getExtractToClass();
+    }
+
+    public String getExtractToClassName() {
+        return ClassUtils.canonicalName( this.extractor.getExtractToClass() );
+    }
+
+    public String toString() {
+        return "[ClassFieldExtractor class=" + this.clazz + " field=" + this.fieldName + "]";
+    }
+
+    public int hashCode() {
+        return getValueType().hashCode() * 17 + getIndex();
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof ClassFieldExtractor) ) {
+            return false;
+        }
+
+        final ClassFieldExtractor other = (ClassFieldExtractor) object;
+
+        return this.extractor.getValueType() == other.getValueType() && this.extractor.getIndex() == other.getIndex();
+    }
+
+    public boolean getBooleanValue(InternalWorkingMemory workingMemory,
+                                   final Object object) {
+        return this.extractor.getBooleanValue( workingMemory,
+                                               object );
+    }
+
+    public byte getByteValue(InternalWorkingMemory workingMemory,
+                             final Object object) {
+        return this.extractor.getByteValue( workingMemory,
+                                            object );
+    }
+
+    public char getCharValue(InternalWorkingMemory workingMemory,
+                             final Object object) {
+        return this.extractor.getCharValue( workingMemory,
+                                            object );
+    }
+
+    public double getDoubleValue(InternalWorkingMemory workingMemory,
+                                 final Object object) {
+        return this.extractor.getDoubleValue( workingMemory,
+                                              object );
+    }
+
+    public float getFloatValue(InternalWorkingMemory workingMemory,
+                               final Object object) {
+        return this.extractor.getFloatValue( workingMemory,
+                                             object );
+    }
+
+    public int getIntValue(InternalWorkingMemory workingMemory,
+                           final Object object) {
+        return this.extractor.getIntValue( workingMemory,
+                                           object );
+    }
+
+    public long getLongValue(InternalWorkingMemory workingMemory,
+                             final Object object) {
+        return this.extractor.getLongValue( workingMemory,
+                                            object );
+    }
+
+    public short getShortValue(InternalWorkingMemory workingMemory,
+                               final Object object) {
+        return this.extractor.getShortValue( workingMemory,
+                                             object );
+    }
+
+    public boolean isNullValue(InternalWorkingMemory workingMemory,
+                               final Object object) {
+        return this.extractor.isNullValue( workingMemory,
+                                           object );
+    }
+
+    public Method getNativeReadMethod() {
+        return this.extractor.getNativeReadMethod();
+    }
+
+    public int getHashCode(InternalWorkingMemory workingMemory,
+                           final Object object) {
+        return this.extractor.getHashCode( workingMemory,
+                                           object );
+    }
+
+    public boolean isGlobal() {
+        return false;
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassFieldExtractorCache.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassFieldExtractorCache.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassFieldExtractorCache.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,107 @@
+package org.drools.base;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * As class field Extractors have some cost to generate
+ * (inspecting the class, and generating classes via ASM)
+ * it makes sense to cache them.
+ * This is that cache.
+ * 
+ * @author Michael Neale
+ *
+ */
+public class ClassFieldExtractorCache {
+    private static final ClassFieldExtractorCache INSTANCE = new ClassFieldExtractorCache();
+
+    private Map                                   cache;
+    private ClassFieldExtractorFactory            factory;
+    
+    private ClassFieldExtractorCache() {
+        this.factory = new ClassFieldExtractorFactory();
+    }
+
+    public static ClassFieldExtractorCache getInstance() {
+        //return INSTANCE;
+        return new ClassFieldExtractorCache();
+    }
+
+    public synchronized ClassFieldExtractor getExtractor(final Class clazz,
+                                                         final String fieldName,
+                                                         ClassLoader classLoader) {
+        if ( cache == null ) {
+            cache = new HashMap();
+        }
+
+        final ExtractorKey key = new ExtractorKey( clazz,
+                                                   fieldName );
+
+        if ( cache.containsKey( key ) ) {
+            return (ClassFieldExtractor) cache.get( key );
+        } else {
+            final ClassFieldExtractor ex = new ClassFieldExtractor( clazz,
+                                                                    fieldName,
+                                                                    classLoader,
+                                                                    factory );
+            cache.put( key,
+                       ex );
+            return ex;
+        }
+    }
+
+    private static class ExtractorKey
+        implements
+        Serializable {
+        private static final long serialVersionUID = 400;
+
+        private final Class       clazz;
+        private final String      fieldName;
+        private final int         hashCode;
+
+        public ExtractorKey(Class clazz,
+                            String fieldName) {
+            super();
+            this.clazz = clazz;
+            this.fieldName = fieldName;
+
+            final int PRIME = 31;
+            int result = 1;
+            result = PRIME * result + ((clazz == null) ? 0 : clazz.hashCode());
+            result = PRIME * result + ((fieldName == null) ? 0 : fieldName.hashCode());
+            this.hashCode = result;
+        }
+
+        public Class getClazz() {
+            return clazz;
+        }
+
+        public String getFieldName() {
+            return fieldName;
+        }
+
+        public int hashCode() {
+            return hashCode;
+        }
+
+        public boolean equals(Object obj) {
+            if ( this == obj ) return true;
+            if ( obj == null ) return false;
+            if ( getClass() != obj.getClass() ) return false;
+            final ExtractorKey other = (ExtractorKey) obj;
+            if ( clazz == null ) {
+                if ( other.clazz != null ) return false;
+            } else if ( !clazz.equals( other.clazz ) ) return false;
+            if ( fieldName == null ) {
+                if ( other.fieldName != null ) return false;
+            } else if ( !fieldName.equals( other.fieldName ) ) return false;
+            return true;
+        }
+
+        public String toString() {
+            return this.clazz + "@" + Math.abs( System.identityHashCode( this.clazz ) ) + "(" + this.fieldName + ")";
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassFieldExtractorFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassFieldExtractorFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassFieldExtractorFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,474 @@
+package org.drools.base;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.asm.ClassWriter;
+import org.drools.asm.Label;
+import org.drools.asm.MethodVisitor;
+import org.drools.asm.Opcodes;
+import org.drools.asm.Type;
+import org.drools.base.extractors.BaseBooleanClassFieldExtractor;
+import org.drools.base.extractors.BaseByteClassFieldExtractor;
+import org.drools.base.extractors.BaseCharClassFieldExtractor;
+import org.drools.base.extractors.BaseDoubleClassFieldExtractor;
+import org.drools.base.extractors.BaseFloatClassFieldExtractor;
+import org.drools.base.extractors.BaseIntClassFieldExtractor;
+import org.drools.base.extractors.BaseLongClassFieldExtractors;
+import org.drools.base.extractors.BaseObjectClassFieldExtractor;
+import org.drools.base.extractors.BaseShortClassFieldExtractor;
+import org.drools.base.extractors.MVELClassFieldExtractor;
+import org.drools.base.extractors.SelfReferenceClassFieldExtractor;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.util.asm.ClassFieldInspector;
+
+/**
+ * This generates subclasses of BaseClassFieldExtractor to provide field extractors.
+ * This should not be used directly, but via ClassFieldExtractor (which ensures that it is 
+ * all nicely serializable).
+ * 
+ * @author Alexander Bagerman
+ * @author Michael Neale
+ */
+
+public class ClassFieldExtractorFactory {
+
+    private static final String           BASE_PACKAGE         = "org/drools/base";
+
+    private static final String           SELF_REFERENCE_FIELD = "this";
+
+    private static final ProtectionDomain PROTECTION_DOMAIN;
+
+    private final Map                     inspectors           = new HashMap();
+
+    private ByteArrayClassLoader          byteArrayClassLoader;
+
+    static {
+        PROTECTION_DOMAIN = (ProtectionDomain) AccessController.doPrivileged( new PrivilegedAction() {
+            public Object run() {
+                return ClassFieldExtractorFactory.class.getProtectionDomain();
+            }
+        } );
+    }
+
+    public BaseClassFieldExtractor getClassFieldExtractor(final Class clazz,
+                                                          final String fieldName,
+                                                          final ClassLoader classLoader) {
+        if ( byteArrayClassLoader == null || byteArrayClassLoader.getParent() != classLoader ) {
+            if ( classLoader == null ) {
+                throw new RuntimeDroolsException( "ClassFieldExtractorFactory cannot have a null parent ClassLoader" );
+            }
+            byteArrayClassLoader = new ByteArrayClassLoader( classLoader );
+        }
+        try {
+            // if it is a self reference
+            if ( SELF_REFERENCE_FIELD.equals( fieldName ) ) {
+                // then just create an instance of the special class field extractor
+                return new SelfReferenceClassFieldExtractor( clazz,
+                                                             fieldName );
+            } else if ( fieldName.indexOf( '.' ) > -1 || fieldName.indexOf( '[' ) > -1 ) {
+                // we need MVEL extractor for expressions
+                return new MVELClassFieldExtractor( clazz,
+                                                    fieldName,
+                                                    classLoader );
+            } else {
+                // otherwise, bytecode generate a specific extractor
+                ClassFieldInspector inspector = (ClassFieldInspector) inspectors.get( clazz );
+                if ( inspector == null ) {
+                    inspector = new ClassFieldInspector( clazz );
+                    inspectors.put( clazz,
+                                    inspector );
+                }
+                final Class fieldType = (Class) inspector.getFieldTypes().get( fieldName );
+                final Method getterMethod = (Method) inspector.getGetterMethods().get( fieldName );
+                if ( fieldType != null && getterMethod != null ) {
+                    final String className = ClassFieldExtractorFactory.BASE_PACKAGE + "/" + Type.getInternalName( clazz ) + Math.abs( System.identityHashCode( clazz ) ) + "$" + getterMethod.getName();
+
+                    // generating byte array to create target class
+                    final byte[] bytes = dump( clazz,
+                                               className,
+                                               getterMethod,
+                                               fieldType,
+                                               clazz.isInterface() );
+                    // use bytes to get a class 
+
+                    final Class newClass = byteArrayClassLoader.defineClass( className.replace( '/',
+                                                                                                '.' ),
+                                                                             bytes,
+                                                                             PROTECTION_DOMAIN );
+                    // instantiating target class
+                    final Integer index = (Integer) inspector.getFieldNames().get( fieldName );
+                    final ValueType valueType = ValueType.determineValueType( fieldType );
+                    final Object[] params = {index, fieldType, valueType};
+                    return (BaseClassFieldExtractor) newClass.getConstructors()[0].newInstance( params );
+                } else {
+                    throw new RuntimeDroolsException( "Field/method '" + fieldName + "' not found for class '" + clazz.getName() + "'" );
+                }
+            }
+        } catch ( final RuntimeDroolsException e ) {
+            throw e;
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( e );
+        }
+    }
+
+    private byte[] dump(final Class originalClass,
+                        final String className,
+                        final Method getterMethod,
+                        final Class fieldType,
+                        final boolean isInterface) throws Exception {
+
+        final ClassWriter cw = new ClassWriter( true );
+
+        final Class superClass = getSuperClassFor( fieldType );
+        buildClassHeader( superClass,
+                          className,
+                          cw );
+
+        //        buildConstructor( superClass,
+        //                          className,
+        //                          cw );
+
+        build3ArgConstructor( superClass,
+                              className,
+                              cw );
+
+        buildGetMethod( originalClass,
+                        className,
+                        superClass,
+                        getterMethod,
+                        cw );
+
+        cw.visitEnd();
+
+        return cw.toByteArray();
+    }
+
+    /**
+     * Builds the class header
+     *  
+     * @param clazz The class to build the extractor for
+     * @param className The extractor class name
+     * @param cw
+     */
+    protected void buildClassHeader(final Class superClass,
+                                    final String className,
+                                    final ClassWriter cw) {
+        cw.visit( Opcodes.V1_5,
+                  Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER,
+                  className,
+                  null,
+                  Type.getInternalName( superClass ),
+                  null );
+
+        cw.visitSource( null,
+                        null );
+    }
+
+    //    /**
+    //     * Creates a constructor for the field extractor receiving
+    //     * the class instance and field name
+    //     * 
+    //     * @param originalClassName
+    //     * @param className
+    //     * @param cw
+    //     */
+    //    private static void buildConstructor(final Class superClazz,
+    //                                         final String className,
+    //                                         final ClassWriter cw) {
+    //        MethodVisitor mv;
+    //        {
+    //            mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+    //                                 "<init>",
+    //                                 Type.getMethodDescriptor( Type.VOID_TYPE,
+    //                                                           new Type[]{Type.getType( Class.class ), Type.getType( String.class )} ),
+    //                                 null,
+    //                                 null );
+    //            mv.visitCode();
+    //            final Label l0 = new Label();
+    //            mv.visitLabel( l0 );
+    //            mv.visitVarInsn( Opcodes.ALOAD,
+    //                             0 );
+    //            mv.visitVarInsn( Opcodes.ALOAD,
+    //                             1 );
+    //            mv.visitVarInsn( Opcodes.ALOAD,
+    //                             2 );
+    //            mv.visitMethodInsn( Opcodes.INVOKESPECIAL,
+    //                                Type.getInternalName( superClazz ),
+    //                                "<init>",
+    //                                Type.getMethodDescriptor( Type.VOID_TYPE,
+    //                                                          new Type[]{Type.getType( Class.class ), Type.getType( String.class )} ) );
+    //            final Label l1 = new Label();
+    //            mv.visitLabel( l1 );
+    //            mv.visitInsn( Opcodes.RETURN );
+    //            final Label l2 = new Label();
+    //            mv.visitLabel( l2 );
+    //            mv.visitLocalVariable( "this",
+    //                                   "L" + className + ";",
+    //                                   null,
+    //                                   l0,
+    //                                   l2,
+    //                                   0 );
+    //            mv.visitLocalVariable( "clazz",
+    //                                   Type.getDescriptor( Class.class ),
+    //                                   null,
+    //                                   l0,
+    //                                   l2,
+    //                                   1 );
+    //            mv.visitLocalVariable( "fieldName",
+    //                                   Type.getDescriptor( String.class ),
+    //                                   null,
+    //                                   l0,
+    //                                   l2,
+    //                                   2 );
+    //            mv.visitMaxs( 0,
+    //                          0 );
+    //            mv.visitEnd();
+    //        }
+    //    }
+
+    /**
+     * Creates a constructor for the field extractor receiving
+     * the index, field type and value type
+     * 
+     * @param originalClassName
+     * @param className
+     * @param cw
+     */
+    private void build3ArgConstructor(final Class superClazz,
+                                      final String className,
+                                      final ClassWriter cw) {
+        MethodVisitor mv;
+        {
+            mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+                                 "<init>",
+                                 Type.getMethodDescriptor( Type.VOID_TYPE,
+                                                           new Type[]{Type.getType( int.class ), Type.getType( Class.class ), Type.getType( ValueType.class )} ),
+                                 null,
+                                 null );
+            mv.visitCode();
+            final Label l0 = new Label();
+            mv.visitLabel( l0 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             0 );
+            mv.visitVarInsn( Opcodes.ILOAD,
+                             1 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             2 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             3 );
+            mv.visitMethodInsn( Opcodes.INVOKESPECIAL,
+                                Type.getInternalName( superClazz ),
+                                "<init>",
+                                Type.getMethodDescriptor( Type.VOID_TYPE,
+                                                          new Type[]{Type.getType( int.class ), Type.getType( Class.class ), Type.getType( ValueType.class )} ) );
+            final Label l1 = new Label();
+            mv.visitLabel( l1 );
+            mv.visitInsn( Opcodes.RETURN );
+            final Label l2 = new Label();
+            mv.visitLabel( l2 );
+            mv.visitLocalVariable( "this",
+                                   "L" + className + ";",
+                                   null,
+                                   l0,
+                                   l2,
+                                   0 );
+            mv.visitLocalVariable( "index",
+                                   Type.getDescriptor( int.class ),
+                                   null,
+                                   l0,
+                                   l2,
+                                   1 );
+            mv.visitLocalVariable( "fieldType",
+                                   Type.getDescriptor( Class.class ),
+                                   null,
+                                   l0,
+                                   l2,
+                                   2 );
+            mv.visitLocalVariable( "valueType",
+                                   Type.getDescriptor( ValueType.class ),
+                                   null,
+                                   l0,
+                                   l2,
+                                   3 );
+            mv.visitMaxs( 0,
+                          0 );
+            mv.visitEnd();
+        }
+    }
+
+    /**
+     * Creates the proxy reader method for the given method
+     * 
+     * @param fieldName
+     * @param fieldFlag
+     * @param method
+     * @param cw
+     */
+    protected void buildGetMethod(final Class originalClass,
+                                  final String className,
+                                  final Class superClass,
+                                  final Method getterMethod,
+                                  final ClassWriter cw) {
+
+        final Class fieldType = getterMethod.getReturnType();
+        Method overridingMethod;
+        try {
+            overridingMethod = superClass.getMethod( getOverridingMethodName( fieldType ),
+                                                     new Class[]{InternalWorkingMemory.class, Object.class} );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( "This is a bug. Please report back to JBoss Rules team.",
+                                              e );
+        }
+        final MethodVisitor mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+                                                 overridingMethod.getName(),
+                                                 Type.getMethodDescriptor( overridingMethod ),
+                                                 null,
+                                                 null );
+
+        mv.visitCode();
+
+        final Label l0 = new Label();
+        mv.visitLabel( l0 );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         2 );
+        mv.visitTypeInsn( Opcodes.CHECKCAST,
+                          Type.getInternalName( originalClass ) );
+
+        if ( originalClass.isInterface() ) {
+            mv.visitMethodInsn( Opcodes.INVOKEINTERFACE,
+                                Type.getInternalName( originalClass ),
+                                getterMethod.getName(),
+                                Type.getMethodDescriptor( getterMethod ) );
+        } else {
+            mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                                Type.getInternalName( originalClass ),
+                                getterMethod.getName(),
+                                Type.getMethodDescriptor( getterMethod ) );
+        }
+        mv.visitInsn( Type.getType( fieldType ).getOpcode( Opcodes.IRETURN ) );
+        final Label l1 = new Label();
+        mv.visitLabel( l1 );
+        mv.visitLocalVariable( "this",
+                               "L" + className + ";",
+                               null,
+                               l0,
+                               l1,
+                               0 );
+        mv.visitLocalVariable( "workingMemory",
+                               Type.getDescriptor( InternalWorkingMemory.class ),
+                               null,
+                               l0,
+                               l1,
+                               1 );
+        mv.visitLocalVariable( "object",
+                               Type.getDescriptor( Object.class ),
+                               null,
+                               l0,
+                               l1,
+                               2 );
+        mv.visitMaxs( 0,
+                      0 );
+        mv.visitEnd();
+    }
+
+    private String getOverridingMethodName(final Class fieldType) {
+        String ret = null;
+        if ( fieldType.isPrimitive() ) {
+            if ( fieldType == char.class ) {
+                ret = "getCharValue";
+            } else if ( fieldType == byte.class ) {
+                ret = "getByteValue";
+            } else if ( fieldType == short.class ) {
+                ret = "getShortValue";
+            } else if ( fieldType == int.class ) {
+                ret = "getIntValue";
+            } else if ( fieldType == long.class ) {
+                ret = "getLongValue";
+            } else if ( fieldType == float.class ) {
+                ret = "getFloatValue";
+            } else if ( fieldType == double.class ) {
+                ret = "getDoubleValue";
+            } else if ( fieldType == boolean.class ) {
+                ret = "getBooleanValue";
+            }
+        } else {
+            ret = "getValue";
+        }
+        return ret;
+    }
+
+    /**
+     * Returns the appropriate Base class field extractor class
+     * for the given fieldType
+     * 
+     * @param fieldType
+     * @return
+     */
+    private Class getSuperClassFor(final Class fieldType) {
+        Class ret = null;
+        if ( fieldType.isPrimitive() ) {
+            if ( fieldType == char.class ) {
+                ret = BaseCharClassFieldExtractor.class;
+            } else if ( fieldType == byte.class ) {
+                ret = BaseByteClassFieldExtractor.class;
+            } else if ( fieldType == short.class ) {
+                ret = BaseShortClassFieldExtractor.class;
+            } else if ( fieldType == int.class ) {
+                ret = BaseIntClassFieldExtractor.class;
+            } else if ( fieldType == long.class ) {
+                ret = BaseLongClassFieldExtractors.class;
+            } else if ( fieldType == float.class ) {
+                ret = BaseFloatClassFieldExtractor.class;
+            } else if ( fieldType == double.class ) {
+                ret = BaseDoubleClassFieldExtractor.class;
+            } else if ( fieldType == boolean.class ) {
+                ret = BaseBooleanClassFieldExtractor.class;
+            }
+        } else {
+            ret = BaseObjectClassFieldExtractor.class;
+        }
+        return ret;
+    }
+
+    /**
+     * Simple classloader
+     * @author Michael Neale
+     */
+    static class ByteArrayClassLoader extends ClassLoader {
+        public ByteArrayClassLoader(final ClassLoader parent) {
+            super( parent );
+        }
+
+        public Class defineClass(final String name,
+                                 final byte[] bytes,
+                                 final ProtectionDomain domain) {
+            return defineClass( name,
+                                bytes,
+                                0,
+                                bytes.length,
+                                domain );
+        }
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassObjectFilter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassObjectFilter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassObjectFilter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,30 @@
+package org.drools.base;
+
+import org.drools.ObjectFilter;
+
+/**
+ * Filters Objects by Class, only accepting Classes of the specified type
+ * @author mproctor
+ *
+ */
+public class ClassObjectFilter implements ObjectFilter {
+    private Class clazz;
+    
+    /** 
+     * The Allowed Class type
+     * @param clazz
+     */
+    public ClassObjectFilter(Class clazz) {
+        this.clazz = clazz;
+    }
+
+    /**
+     * Returning true means the Iterator accepts, and thus returns, the current Object's Class type.
+     * @param object
+     * @return
+     */    
+    public boolean accept(Object object) {
+        return this.clazz.isAssignableFrom( object.getClass() );
+    }
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassObjectType.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassObjectType.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassObjectType.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,168 @@
+package org.drools.base;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.ObjectType;
+
+/**
+ * Java class semantics <code>ObjectType</code>.
+ * 
+ * @author <a href="mailto:bob at werken.com">bob at werken.com </a>
+ * 
+ * @version $Id: ClassObjectType.java,v 1.5 2005/02/04 02:13:36 mproctor Exp $
+ */
+public class ClassObjectType
+    implements
+    ObjectType {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    /** Java object class. */
+    protected Class           objectTypeClass;
+
+    protected ValueType       valueType;
+
+    private boolean           isEvent;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    /**
+     * Creates a new class object type with shadow disabled.
+     * 
+     * @param objectTypeClass
+     *            Java object class.
+     */
+    public ClassObjectType(final Class objectTypeClass) {
+        this( objectTypeClass, false );
+    }
+
+    /**
+     * Creates a new class object type
+     * 
+     * @param objectTypeClass the class represented by this class object type
+     * @param isEvent true if it is an event class, false otherwise
+     */
+    public ClassObjectType(final Class objectTypeClass, final boolean isEvent) {
+        this.objectTypeClass = objectTypeClass;
+        this.isEvent = isEvent;
+        this.valueType = ValueType.determineValueType( objectTypeClass );
+    }
+
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+
+    /**
+     * Return the Java object class.
+     * 
+     * @return The Java object class.
+     */
+    public Class getClassType() {
+        return this.objectTypeClass;
+    }
+
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // org.drools.spi.ObjectType
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+    /**
+     * Determine if the passed <code>Class</code> matches to the object type
+     * defined by this <code>objectType</code> instance.
+     * 
+     * @param clazz
+     *            The <code>Class</code> to test.
+     * 
+     * @return <code>true</code> if the <code>Class</code> matches this
+     *         object type, else <code>false</code>.
+     */
+    public boolean matchesClass(final Class clazz) {
+        return getClassType().isAssignableFrom( clazz );
+    }
+
+    /**
+     * Determine if the passed <code>Object</code> belongs to the object type
+     * defined by this <code>objectType</code> instance.
+     * 
+     * @param object
+     *            The <code>Object</code> to test.
+     * 
+     * @return <code>true</code> if the <code>Object</code> matches this
+     *         object type, else <code>false</code>.
+     */
+    public boolean matches(final Object object) {
+        return getClassType().isInstance( object );
+    }
+
+    public boolean isAssignableFrom(Object object) {
+        return this.objectTypeClass.isAssignableFrom( (Class) object );
+    }
+
+    public boolean isAssignableFrom(ObjectType objectType) {
+        if ( !(objectType instanceof ClassObjectType) ) {
+            return false;
+        } else {
+            return this.objectTypeClass.isAssignableFrom( ((ClassObjectType) objectType).getClassType() );
+        }
+    }
+
+    public ValueType getValueType() {
+        return this.valueType;
+    }
+
+    public boolean isEvent() {
+        return isEvent;
+    }
+
+    public void setEvent(boolean isEvent) {
+        this.isEvent = isEvent;
+    }
+
+    public String toString() {
+        return "[ClassObjectType "+( this.isEvent ? "event=" : "class=" )+ getClassType().getName() + "]";
+    }
+
+    /**
+     * Determine if another object is equal to this.
+     * 
+     * @param object
+     *            The object to test.
+     * 
+     * @return <code>true</code> if <code>object</code> is equal to this,
+     *         otherwise <code>false</code>.
+     */
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || object.getClass() != ClassObjectType.class ) {
+            return false;
+        }
+        
+        return this.objectTypeClass == ((ClassObjectType) object).objectTypeClass;
+    }
+
+    public int hashCode() {
+        return this.objectTypeClass.hashCode();
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassTypeResolver.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassTypeResolver.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ClassTypeResolver.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,294 @@
+package org.drools.base;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.drools.RuntimeDroolsException;
+
+public class ClassTypeResolver
+    implements
+    TypeResolver {
+    private Set<String>      imports          = Collections.emptySet();
+
+    private ClassLoader      classLoader;
+
+    private Map              cachedImports    = new HashMap();
+
+    private static final Map internalNamesMap = new HashMap();
+    static {
+        internalNamesMap.put( "int",
+                              "I" );
+        internalNamesMap.put( "boolean",
+                              "Z" );
+        internalNamesMap.put( "float",
+                              "F" );
+        internalNamesMap.put( "long",
+                              "J" );
+        internalNamesMap.put( "short",
+                              "S" );
+        internalNamesMap.put( "byte",
+                              "B" );
+        internalNamesMap.put( "double",
+                              "D" );
+        internalNamesMap.put( "char",
+                              "C" );
+    }
+
+    public ClassTypeResolver(final Set<String> imports,
+                             final ClassLoader classLoader) {
+        this.imports = imports;
+
+        if ( classLoader == null ) {
+            throw new RuntimeDroolsException( "ClassTypeResolver cannot have a null parent ClassLoader" );
+        }
+
+        this.classLoader = classLoader;
+    }
+
+    public void setClassLoader(ClassLoader classLoader) {
+        this.classLoader = classLoader;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.drools.semantics.base.Importer#getImports( Class clazz )
+     */
+    /* (non-Javadoc)
+     * @see org.drools.semantics.java.TypeResolver#getImports()
+     */
+    public Set<String> getImports() {
+        return this.imports;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.drools.semantics.base.Importer#addImports(org.drools.spi.ImportEntry)
+     */
+    /* (non-Javadoc)
+     * @see org.drools.semantics.java.TypeResolver#addImport(java.lang.String)
+     */
+    public void addImport(final String importEntry) {
+        if ( this.imports == Collections.EMPTY_SET ) {
+            this.imports = new HashSet<String>();
+        }
+        this.imports.add( importEntry );
+    }
+
+    public Class lookupFromCache(final String className) {
+        return (Class) this.cachedImports.get( className );
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.drools.semantics.base.Importer#importClass(java.lang.ClassLoader,
+     *      java.lang.String)
+     */
+    /* (non-Javadoc)
+     * @see org.drools.semantics.java.TypeResolver#resolveType(java.lang.String)
+     */
+    public Class resolveType(String className) throws ClassNotFoundException {
+        Class clazz = null;
+        boolean isArray = false;
+        final StringBuffer arrayClassName = new StringBuffer();
+
+        //is the class a primitive type ?
+        if ( internalNamesMap.containsKey( className ) ) {
+            clazz = Class.forName( "[" + internalNamesMap.get( className ),
+                                   true,
+                                   this.classLoader ).getComponentType();
+            // Could also be a primitive array
+        } else if ( className.indexOf( '[' ) > 0 ) {
+            isArray = true;
+            int bracketIndex = className.indexOf( '[' );
+            final String componentName = className.substring( 0,
+                                                              bracketIndex );
+            arrayClassName.append( '[' );
+            while ( (bracketIndex = className.indexOf( '[',
+                                                       bracketIndex + 1 )) > 0 ) {
+                arrayClassName.append( '[' );
+            }
+            className = componentName;
+        }
+
+        if ( clazz == null ) {
+            // Now try the package object type cache
+            clazz = lookupFromCache( className );
+        }
+
+        // try loading className
+        if ( clazz == null ) {
+            try {
+                clazz = this.classLoader.loadClass( className );
+            } catch ( final ClassNotFoundException e ) {
+                clazz = null;
+            }
+        }
+
+        // Now try the className with each of the given imports
+        if ( clazz == null ) {
+            final Set validClazzCandidates = new HashSet();
+
+            final Iterator it = this.imports.iterator();
+            while ( it.hasNext() ) {
+                clazz = importClass( (String) it.next(),
+                                     className );
+                if ( clazz != null ) {
+                    validClazzCandidates.add( clazz );
+                }
+            }
+
+            // If there are more than one possible resolutions, complain about
+            // the ambiguity
+            if ( validClazzCandidates.size() > 1 ) {
+                final StringBuffer sb = new StringBuffer();
+                final Iterator clazzCandIter = validClazzCandidates.iterator();
+                while ( clazzCandIter.hasNext() ) {
+                    if ( 0 != sb.length() ) {
+                        sb.append( ", " );
+                    }
+                    sb.append( ((Class) clazzCandIter.next()).getName() );
+                }
+                throw new Error( "Unable to find unambiguously defined class '" + className + "', candidates are: [" + sb.toString() + "]" );
+            } else if ( validClazzCandidates.size() == 1 ) {
+                clazz = (Class) validClazzCandidates.toArray()[0];
+            } else {
+                clazz = null;
+            }
+
+        }
+
+        // Now try the java.lang package
+        if ( clazz == null ) {
+            clazz = defaultClass( className );
+        }
+
+        // If array component class was found, try to resolve the array class of it
+        if ( isArray ) {
+            if ( clazz == null && internalNamesMap.containsKey( className ) ) {
+                arrayClassName.append( internalNamesMap.get( className ) );
+            } else {
+                if ( clazz != null ) {
+                    arrayClassName.append( "L" ).append( clazz.getName() ).append( ";" );
+                } else {
+                    // we know we will probably not be able to resolve this name, but nothing else we can do.
+                    arrayClassName.append( "L" ).append( className ).append( ";" );
+                }
+            }
+            try {
+                clazz = Class.forName( arrayClassName.toString() );
+            } catch ( final ClassNotFoundException e ) {
+                clazz = null;
+            }
+        }
+
+        // We still can't find the class so throw an exception
+        if ( clazz == null ) {
+            throw new ClassNotFoundException( "Unable to find class '" + className + "'" );
+        }
+
+        return clazz;
+    }
+
+    private Class importClass(final String importText,
+                              final String className) {
+        String qualifiedClass = null;
+        Class clazz = null;
+
+        if ( importText.endsWith( "*" ) ) {
+            qualifiedClass = importText.substring( 0,
+                                                   importText.indexOf( '*' ) ) + className;
+        } else if ( importText.endsWith( "." + className ) ) {
+            qualifiedClass = importText;
+        } else if ( importText.equals( className ) ) {
+            qualifiedClass = importText;
+        }
+
+        if ( qualifiedClass != null ) {
+            try {
+                clazz = this.classLoader.loadClass( qualifiedClass );
+            } catch ( final ClassNotFoundException e ) {
+                clazz = null;
+            }
+
+            // maybe its a nested class?
+            if ( clazz == null ) {
+                try {
+                    final int lastIndex = qualifiedClass.lastIndexOf( '.' );
+                    qualifiedClass = qualifiedClass.substring( 0,
+                                                               lastIndex ) + "$" + qualifiedClass.substring( lastIndex + 1 );
+                    clazz = this.classLoader.loadClass( qualifiedClass );
+                } catch ( final ClassNotFoundException e ) {
+                    clazz = null;
+                }
+            }
+        }
+
+        if ( clazz != null ) {
+            if ( this.cachedImports == Collections.EMPTY_MAP ) {
+                this.cachedImports = new HashMap();
+            }
+
+            this.cachedImports.put( className,
+                                    clazz );
+        }
+
+        return clazz;
+    }
+
+    private Class defaultClass(final String className) {
+        final String qualifiedClass = "java.lang." + className;
+        Class clazz = null;
+        try {
+            clazz = this.classLoader.loadClass( qualifiedClass );
+        } catch ( final ClassNotFoundException e ) {
+            // do nothing
+        }
+        if ( clazz != null ) {
+            if ( this.cachedImports == Collections.EMPTY_MAP ) {
+                this.cachedImports = new HashMap();
+            }
+            this.cachedImports.put( className,
+                                    clazz );
+        }
+        return clazz;
+    }
+
+    public boolean isEmpty() {
+        return this.imports.isEmpty();
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.drools.base.TypeResolver#getFullTypeName(java.lang.String)
+     */
+	public String getFullTypeName(String shortName) throws ClassNotFoundException {
+
+		Class clz = resolveType(shortName);
+		if (clz == null)  throw new IllegalArgumentException("Unable to resolve the full type name for " + shortName);
+		return clz.getName();
+
+	}
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/CopyIdentifiersGlobalExporter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/CopyIdentifiersGlobalExporter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/CopyIdentifiersGlobalExporter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,54 @@
+/**
+ * 
+ */
+package org.drools.base;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.WorkingMemory;
+import org.drools.common.InternalRuleBase;
+import org.drools.spi.GlobalExporter;
+import org.drools.spi.GlobalResolver;
+
+/**
+ * Creates a new GlobalResolver consisting of just the identifiers specified in the String[].
+ * If the String[] is null, or the default constructor is used, then all globals defined in the RuleBase
+ * will be copied.
+ *
+ */
+public class CopyIdentifiersGlobalExporter implements GlobalExporter {
+    private String[] identifiers;
+    
+    /**
+     * All identifiers will be copied
+     *
+     */
+    public CopyIdentifiersGlobalExporter() {
+        this.identifiers = null;
+    }
+    
+    /**
+     * Specified identifiers will be copied
+     * @param identifiers
+     */
+    public CopyIdentifiersGlobalExporter(String[] identifiers) {
+        this.identifiers = identifiers;
+    }
+    
+    public GlobalResolver export(WorkingMemory workingMemory) {
+        if ( this.identifiers == null || this.identifiers.length == 0 ) {
+            // no identifiers, to get all the identifiers from that defined in
+            // the rulebase
+            Map map = ((InternalRuleBase)workingMemory.getRuleBase()).getGlobals();
+            this.identifiers = new String[ map.size() ];
+            this.identifiers = (String[]) map.keySet().toArray( this.identifiers );
+        }
+        
+        Map map = new HashMap(identifiers.length);
+        for ( int i = 0, length = identifiers.length; i < length; i++ ) {
+            map.put( identifiers[i], workingMemory.getGlobal( identifiers[i] ) );
+        }
+        return new MapGlobalResolver(map);
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/DefaultConsequenceExceptionHandler.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/DefaultConsequenceExceptionHandler.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/DefaultConsequenceExceptionHandler.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,18 @@
+package org.drools.base;
+
+import org.drools.WorkingMemory;
+import org.drools.spi.Activation;
+import org.drools.spi.ConsequenceException;
+import org.drools.spi.ConsequenceExceptionHandler;
+
+public class DefaultConsequenceExceptionHandler implements ConsequenceExceptionHandler {
+
+    public void handleException(Activation activation,
+                                WorkingMemory workingMemory,
+                                Exception exception) {
+        exception.printStackTrace();
+        throw new ConsequenceException( exception,
+                                        activation.getRule() );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/DefaultKnowledgeHelper.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/DefaultKnowledgeHelper.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/DefaultKnowledgeHelper.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,208 @@
+package org.drools.base;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.FactException;
+import org.drools.FactHandle;
+import org.drools.WorkingMemory;
+import org.drools.common.InternalWorkingMemoryActions;
+import org.drools.rule.Declaration;
+import org.drools.rule.GroupElement;
+import org.drools.rule.Rule;
+import org.drools.spi.Activation;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.Tuple;
+
+public class DefaultKnowledgeHelper
+    implements
+    KnowledgeHelper {
+
+    private static final long                  serialVersionUID = 400L;
+
+    private Rule                               rule;
+    private GroupElement                       subrule;
+    private Activation                         activation;
+    private Tuple                              tuple;
+    private final InternalWorkingMemoryActions workingMemory;
+
+    public DefaultKnowledgeHelper(final WorkingMemory workingMemory) {
+        this.workingMemory = (InternalWorkingMemoryActions) workingMemory;
+    }
+
+    public void setActivation(final Activation agendaItem) {
+        this.rule = agendaItem.getRule();
+        this.subrule = agendaItem.getSubRule();
+        this.activation = agendaItem;
+        this.tuple = agendaItem.getTuple();
+    }
+    
+    public void reset() {
+        this.rule = null;
+        this.subrule = null;
+        this.activation = null;
+        this.tuple = null;
+    }
+
+    public void insert(final Object object) throws FactException {
+        insert( object,
+                false );
+    }
+
+    public void insert(final Object object,
+                       final boolean dynamic) throws FactException {
+        this.workingMemory.insert( object,
+                                   dynamic,
+                                   false,
+                                   this.rule,
+                                   this.activation );
+    }
+    
+    public void insertLogical(final Object object) throws FactException {
+        insertLogical( object,
+                       false );
+    }
+
+    public void insertLogical(final Object object,
+                              final boolean dynamic) throws FactException {
+        this.workingMemory.insert( object,
+                                   dynamic,
+                                   true,
+                                   this.rule,
+                                   this.activation );
+    }
+    
+    public void update(final FactHandle handle,
+                       final Object newObject) throws FactException {
+        // only update if this fact exists in the wm
+        this.workingMemory.update( handle,
+                                   newObject,
+                                   this.rule,
+                                   this.activation );
+    }
+
+    public void update(final Object object) throws FactException {
+        FactHandle handle = this.workingMemory.getFactHandleByIdentity( object );
+        if ( handle == null ) {
+            throw new FactException( "Update error: handle not found for object: " + object + ". Is it in the working memory?" );
+        }
+        // only update if this fact exists in the wm
+        this.workingMemory.update( handle,
+                                   object,
+                                   this.rule,
+                                   this.activation );
+    }
+
+    public void retract(final FactHandle handle) throws FactException {
+        this.workingMemory.retract( handle,
+                                    true,
+                                    true,
+                                    this.rule,
+                                    this.activation );
+    }
+
+    public void retract(final Object object) throws FactException {
+        FactHandle handle = this.workingMemory.getFactHandleByIdentity( object );
+        if ( handle == null ) {
+            throw new FactException( "Retract error: handle not found for object: " + object + ". Is it in the working memory?" );
+        }
+        this.workingMemory.retract( handle,
+                                    true,
+                                    true,
+                                    this.rule,
+                                    this.activation );
+    }
+
+    public void modifyRetract(final Object object) {
+        FactHandle handle = this.workingMemory.getFactHandleByIdentity( object );
+        this.workingMemory.modifyRetract( handle, rule, activation );
+    }
+
+    public void modifyRetract(final FactHandle factHandle) {
+        this.workingMemory.modifyRetract( factHandle, rule, activation );
+    }
+
+    public void modifyInsert(final Object object) {
+        FactHandle handle = this.workingMemory.getFactHandleByIdentity( object );
+        this.workingMemory.modifyInsert( handle, object, rule, activation );
+    }
+
+    public void modifyInsert(final FactHandle factHandle,
+                             final Object object) {
+        this.workingMemory.modifyInsert( factHandle, object, rule, activation );        
+    }
+
+    public Rule getRule() {
+        return this.rule;
+    }
+
+    //    public List getObjects() {
+    //        return null; //this.workingMemory.getObjects();
+    //    }
+    //
+    //    public List getObjects(final Class objectClass) {
+    //        return null; //this.workingMemory.getObjects( objectClass );
+    //    }
+    //
+    //    public void clearAgenda() {
+    //        this.workingMemory.clearAgenda();
+    //    }
+    //
+    //    public void clearAgendaGroup(final String group) {
+    //        this.workingMemory.clearAgendaGroup( group );
+    //    }
+
+    public Tuple getTuple() {
+        return this.tuple;
+    }
+
+    public WorkingMemory getWorkingMemory() {
+        return this.workingMemory;
+    }
+
+    public Activation getActivation() {
+        return this.activation;
+    }
+
+    //    public QueryResults getQueryResults(final String query) {
+    //        return this.workingMemory.getQueryResults( query );
+    //    }
+    //
+    //    public AgendaGroup getFocus() {
+    //        return this.workingMemory.getFocus();
+    //    }
+    //
+    public void setFocus(final String focus) {
+        this.workingMemory.setFocus( focus );
+    }
+
+    //
+    //    public void setFocus(final AgendaGroup focus) {
+    //        this.workingMemory.setFocus( focus );
+    //    }
+    
+    public Object get(final Declaration declaration) {
+        return declaration.getValue( workingMemory, this.tuple.get( declaration ).getObject() );
+    }    
+
+    public Declaration getDeclaration(final String identifier) {
+        return (Declaration) this.subrule.getOuterDeclarations().get( identifier );
+    }
+    
+    public void halt() {
+        this.workingMemory.halt();
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/DelegateJavaFactHandler.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/DelegateJavaFactHandler.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/DelegateJavaFactHandler.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,133 @@
+package org.drools.base;
+
+import org.drools.FactHandle;
+import org.drools.WorkingMemory;
+import org.drools.spi.JavaFact;
+
+public class DelegateJavaFactHandler
+    implements
+    JavaFact {
+    private JavaFactRegistryEntry[] entries;
+
+    public JavaFactRegistryEntry[] listWorkingMemories() {
+        return this.entries;
+    }
+
+    public boolean register(final WorkingMemory workingMemory) {
+        if ( workingMemory == null ) {
+            return false;
+        }
+
+        if ( isRegistered( workingMemory ) ) {
+            return false;
+        }
+
+        final JavaFactRegistryEntry[] newEntries;
+        int position;
+        if ( this.entries == null ) {
+            newEntries = new JavaFactRegistryEntry[1];
+            position = 0;
+        } else {
+            final int newLength = this.entries.length + 1;
+            newEntries = new JavaFactRegistryEntry[newLength];
+            System.arraycopy( this.entries,
+                              0,
+                              newEntries,
+                              0,
+                              newLength - 1 );
+            position = this.entries.length;
+        }
+
+        final FactHandle handle = workingMemory.insert( this );
+
+        newEntries[position] = new JavaFactRegistryEntry( workingMemory,
+                                                          handle );
+
+        this.entries = newEntries;
+        return true;
+    }
+
+    public void unregisterAll() {
+        for ( int i = 0, length = this.entries.length; i < length; i++ ) {
+            final WorkingMemory workingMemory = this.entries[i].getWorkingMemory();
+            final FactHandle handle = this.entries[i].getFactHandle();
+            workingMemory.retract( handle );
+        }
+
+    }
+
+    public boolean unregister(final WorkingMemory workingMemory) {
+        if ( this.entries == null ) {
+            return false;
+        }
+
+        //  If there is only one entry, see if it matched and if so null
+        if ( this.entries.length == 1 && this.entries[0].getWorkingMemory() == workingMemory ) {
+            this.entries = null;
+            return true;
+        }
+
+        //  try the first
+        if ( this.entries[0].getWorkingMemory() == workingMemory ) {
+            final JavaFactRegistryEntry[] newEntries = new JavaFactRegistryEntry[this.entries.length - 1];
+            System.arraycopy( this.entries,
+                              1,
+                              newEntries,
+                              0,
+                              newEntries.length );
+            this.entries = newEntries;
+            return true;
+        }
+
+        // try the last
+        if ( this.entries[this.entries.length - 1].getWorkingMemory() == workingMemory ) {
+            final JavaFactRegistryEntry[] newEntries = new JavaFactRegistryEntry[this.entries.length - 1];
+            System.arraycopy( this.entries,
+                              0,
+                              newEntries,
+                              0,
+                              newEntries.length );
+            this.entries = newEntries;
+            return true;
+        }
+
+        // try middle
+        for ( int i = 0, length = this.entries.length; i < length; i++ ) {
+            if ( this.entries[i].getWorkingMemory() == workingMemory ) {
+                final JavaFactRegistryEntry[] newEntries = new JavaFactRegistryEntry[this.entries.length - 1];
+                System.arraycopy( this.entries,
+                                  0,
+                                  newEntries,
+                                  0,
+                                  i );
+                System.arraycopy( this.entries,
+                                  i + 1,
+                                  newEntries,
+                                  i,
+                                  newEntries.length - 1 );
+                this.entries = newEntries;
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean isRegistered(final WorkingMemory workingMemory) {
+        if ( this.entries == null ) {
+            return false;
+        }
+
+        for ( int i = 0, length = this.entries.length; i < length; i++ ) {
+            if ( this.entries[i].getWorkingMemory() == workingMemory ) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public int[] getChanges() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/DroolsQuery.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/DroolsQuery.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/DroolsQuery.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,68 @@
+package org.drools.base;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public final class DroolsQuery {
+    private final String name;
+    private final Object[] args;
+
+    private static final Object[] EMPTY_PARAMS = new Object[0];
+
+    public DroolsQuery(final String name) {
+        super();
+        this.name = name;
+        this.args = EMPTY_PARAMS;
+    }
+
+    public DroolsQuery(final String name, final Object[] params) {
+        super();
+        this.name = name;
+        if ( params != null ) {
+            this.args = params;
+        } else {
+            this.args = EMPTY_PARAMS;
+        }
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public Object[] getArguments() {
+        return this.args;
+    }
+
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + ((this.name == null) ? 0 : this.name.hashCode());
+        return result;
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || getClass() != object.getClass() ) {
+            return false;
+        }
+
+        final DroolsQuery other = (DroolsQuery) object;
+        return this.name.equals( other.name );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/FieldFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/FieldFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/FieldFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,237 @@
+package org.drools.base;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import org.drools.base.field.BooleanFieldImpl;
+import org.drools.base.field.DoubleFieldImpl;
+import org.drools.base.field.LongFieldImpl;
+import org.drools.base.field.ObjectFieldImpl;
+import org.drools.spi.FieldValue;
+
+public class FieldFactory {
+    private static final FieldFactory INSTANCE = new FieldFactory();
+
+    public static FieldFactory getInstance() {
+        return FieldFactory.INSTANCE;
+    }
+
+    private FieldFactory() {
+
+    }
+
+    public static FieldValue getFieldValue(final String value,
+                                           ValueType valueType) {
+        FieldValue field = null;
+        if ( value == null ) {
+            valueType = ValueType.NULL_TYPE;
+        }
+
+        if ( valueType == ValueType.NULL_TYPE ) {
+            field = new ObjectFieldImpl( null );
+        } else if ( valueType == ValueType.PCHAR_TYPE ) {
+            field = new LongFieldImpl( value.charAt( 0 ) );
+        } else if ( valueType == ValueType.PBYTE_TYPE ) {
+            field = new LongFieldImpl( Long.parseLong( value ) );
+        } else if ( valueType == ValueType.PSHORT_TYPE ) {
+            field = new LongFieldImpl( Long.parseLong( value ) );
+        } else if ( valueType == ValueType.PINTEGER_TYPE ) {
+            field = new LongFieldImpl( Long.parseLong( stripNumericType( value ) ) );
+        } else if ( valueType == ValueType.PLONG_TYPE ) {
+            field = new LongFieldImpl( Long.parseLong( stripNumericType( value ) ) );
+        } else if ( valueType == ValueType.PFLOAT_TYPE ) {
+            field = new DoubleFieldImpl( Float.parseFloat( stripNumericType( value ) ) );
+        } else if ( valueType == ValueType.PDOUBLE_TYPE ) {
+            field = new DoubleFieldImpl( Double.parseDouble( stripNumericType( value ) ) );
+        } else if ( valueType == ValueType.PBOOLEAN_TYPE ) {
+            field = new BooleanFieldImpl( Boolean.valueOf( value ).booleanValue() );
+        } else if ( valueType == ValueType.CHAR_TYPE ) {
+            field = new ObjectFieldImpl( new Character( value.charAt( 0 ) ) );
+        } else if ( valueType == ValueType.BYTE_TYPE ) {
+            field = new ObjectFieldImpl( new Byte( value ) );
+        } else if ( valueType == ValueType.SHORT_TYPE ) {
+            field = new ObjectFieldImpl( new Short( value ) );
+        } else if ( valueType == ValueType.INTEGER_TYPE ) {
+            field = new ObjectFieldImpl( new Integer( stripNumericType( value ) ) );
+        } else if ( valueType == ValueType.LONG_TYPE ) {
+            field = new ObjectFieldImpl( new Long( stripNumericType( value ) ) );
+        } else if ( valueType == ValueType.FLOAT_TYPE ) {
+            field = new ObjectFieldImpl( new Float( stripNumericType( value ) ) );
+        } else if ( valueType == ValueType.DOUBLE_TYPE ) {
+            field = new ObjectFieldImpl( new Double( stripNumericType( value ) ) );
+        } else if ( valueType == ValueType.BOOLEAN_TYPE ) {
+            field = new ObjectFieldImpl( Boolean.valueOf( value ) );
+        } else if ( valueType == ValueType.STRING_TYPE ) {
+            field = new ObjectFieldImpl( value.intern() );
+        } else if ( valueType == ValueType.DATE_TYPE ) {
+            //MN: I think its fine like this, seems to work !
+            field = new ObjectFieldImpl( value );
+        } else if ( valueType == ValueType.ARRAY_TYPE ) {
+            //MN: I think its fine like this.
+            field = new ObjectFieldImpl( value );
+        } else if ( valueType == ValueType.OBJECT_TYPE ) {
+            field = new ObjectFieldImpl( value );
+        } else if ( valueType == ValueType.BIG_DECIMAL_TYPE ) {
+            field = new ObjectFieldImpl( new BigDecimal( value ) );
+        } else if ( valueType == ValueType.BIG_INTEGER_TYPE ) {
+            field = new ObjectFieldImpl( new BigInteger( value ) );
+        }
+
+        return field;
+    }
+
+    public static FieldValue getFieldValue(final Object value,
+                                           ValueType valueType) {
+        FieldValue field = null;
+        if ( value == null ) {
+            valueType = ValueType.NULL_TYPE;
+        }
+
+        if ( valueType == ValueType.NULL_TYPE ) {
+            field = new ObjectFieldImpl( null );
+        } else if ( valueType == ValueType.PCHAR_TYPE ) {
+            if( value instanceof String && ((String)value).length() == 1 ) {
+                field = new LongFieldImpl( ((String) value).charAt(0) );
+            } else {
+                field = new LongFieldImpl( ((Character) value).charValue() );
+            } 
+        } else if ( valueType == ValueType.PBYTE_TYPE ) {
+            if( value instanceof String ) {
+                field = new LongFieldImpl( Byte.parseByte( (String) value) );
+            } else {
+                field = new LongFieldImpl( ((Number) value).byteValue() );
+            } 
+        } else if ( valueType == ValueType.PSHORT_TYPE ) {
+            if( value instanceof String ) {
+                field = new LongFieldImpl( Short.parseShort( (String) value) );
+            } else {
+                field = new LongFieldImpl( ((Number) value).shortValue() );
+            } 
+        } else if ( valueType == ValueType.PINTEGER_TYPE ) {
+            if( value instanceof String ) {
+                field = new LongFieldImpl( Integer.parseInt( stripNumericType( (String) value ) ) );
+            } else {
+                field = new LongFieldImpl( ((Number) value).intValue() );
+            } 
+        } else if ( valueType == ValueType.PLONG_TYPE ) {
+            if( value instanceof String ) {
+                field = new LongFieldImpl( Long.parseLong( stripNumericType( (String) value ) ) );
+            } else {
+                field = new LongFieldImpl( ((Number) value).longValue() );
+            } 
+        } else if ( valueType == ValueType.PFLOAT_TYPE ) {
+            if( value instanceof String ) {
+                field = new DoubleFieldImpl( Float.parseFloat( stripNumericType( (String) value ) ) );
+            } else {
+                field = new DoubleFieldImpl( ((Number) value).floatValue() );
+            } 
+        } else if ( valueType == ValueType.PDOUBLE_TYPE ) {
+            if( value instanceof String ) {
+                field = new DoubleFieldImpl( Double.parseDouble( stripNumericType( (String) value ) ) );
+            } else {
+                field = new DoubleFieldImpl( ((Number) value).doubleValue() );
+            } 
+        } else if ( valueType == ValueType.PBOOLEAN_TYPE ) {
+            if( value instanceof String ) {
+                field = new BooleanFieldImpl( Boolean.valueOf( (String) value).booleanValue() );
+            } else {
+                field = new BooleanFieldImpl( ((Boolean) value).booleanValue() );
+            } 
+        } else if ( valueType == ValueType.CHAR_TYPE ) {
+            field = new ObjectFieldImpl( value );
+        } else if ( valueType == ValueType.BYTE_TYPE ) {
+            field = new ObjectFieldImpl( value );
+        } else if ( valueType == ValueType.SHORT_TYPE ) {
+            field = new ObjectFieldImpl( value );
+        } else if ( valueType == ValueType.INTEGER_TYPE ) {
+            field = new ObjectFieldImpl( value );
+        } else if ( valueType == ValueType.LONG_TYPE ) {
+            field = new ObjectFieldImpl( value );
+        } else if ( valueType == ValueType.FLOAT_TYPE ) {
+            field = new ObjectFieldImpl( value );
+        } else if ( valueType == ValueType.DOUBLE_TYPE ) {
+            field = new ObjectFieldImpl( value );
+        } else if ( valueType == ValueType.BOOLEAN_TYPE ) {
+            field = new ObjectFieldImpl( value );
+        } else if ( valueType == ValueType.STRING_TYPE ) {
+            field = new ObjectFieldImpl( value );
+        } else if ( valueType == ValueType.DATE_TYPE ) {
+            //MN: I think its fine like this, seems to work !
+            field = new ObjectFieldImpl( value );
+        } else if ( valueType == ValueType.ARRAY_TYPE ) {
+            //MN: I think its fine like this.
+            field = new ObjectFieldImpl( value );
+        } else if ( valueType == ValueType.OBJECT_TYPE ) {
+            field = new ObjectFieldImpl( value );
+        } else if ( valueType == ValueType.BIG_DECIMAL_TYPE ) {
+            field = new ObjectFieldImpl( value );
+        } else if ( valueType == ValueType.BIG_INTEGER_TYPE ) {
+            field = new ObjectFieldImpl( value );
+        }
+
+        return field;
+    }
+
+    public static FieldValue getFieldValue(final Object value) {
+        return new ObjectFieldImpl( value );
+    }
+
+    public static FieldValue getFieldValue(final byte value) {
+        return new LongFieldImpl( value );
+    }
+
+    public static FieldValue getFieldValue(final short value) {
+        return new LongFieldImpl( value );
+    }
+
+    public static FieldValue getFieldValue(final char value) {
+        return new LongFieldImpl( value );
+    }
+
+    public static FieldValue getFieldValue(final int value) {
+        return new LongFieldImpl( value );
+    }
+
+    public static FieldValue getFieldValue(final long value) {
+        return new LongFieldImpl( value );
+    }
+
+    public static FieldValue getFieldValue(final boolean value) {
+        return new BooleanFieldImpl( value );
+    }
+
+    public static FieldValue getFieldValue(final float value) {
+        return new DoubleFieldImpl( value );
+    }
+
+    public static FieldValue getFieldValue(final double value) {
+        return new DoubleFieldImpl( value );
+    }
+
+    private static String stripNumericType(String value) {
+        // incase a user adds a f or l, strip it as its not needed
+        if ( Character.getType( value.charAt( value.length() - 1 ) ) != Character.DECIMAL_DIGIT_NUMBER ) {
+            value = value.substring( 0,
+                                     value.length() - 1 );
+        }
+
+        return value;
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/FireAllRulesRuleBaseUpdateListener.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/FireAllRulesRuleBaseUpdateListener.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/FireAllRulesRuleBaseUpdateListener.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,32 @@
+/**
+ * 
+ */
+package org.drools.base;
+
+import java.io.Serializable;
+
+import org.drools.StatefulSession;
+import org.drools.event.BeforeRuleBaseUnlockedEvent;
+import org.drools.event.DefaultRuleBaseEventListener;
+import org.drools.spi.RuleBaseUpdateListener;
+
+public class FireAllRulesRuleBaseUpdateListener extends DefaultRuleBaseEventListener
+    implements
+    RuleBaseUpdateListener,
+    Serializable {
+    private StatefulSession session;
+
+    public FireAllRulesRuleBaseUpdateListener() {
+
+    }
+
+    public void setSession(StatefulSession session) {
+        this.session = session;
+    }
+
+    public void beforeRuleBaseUnlocked(BeforeRuleBaseUnlockedEvent event) {
+        if ( session.getRuleBase().getAdditionsSinceLock() > 0 ) {
+            session.fireAllRules();
+        }
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/JavaFactRegistryEntry.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/JavaFactRegistryEntry.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/JavaFactRegistryEntry.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,28 @@
+/**
+ * 
+ */
+package org.drools.base;
+
+import org.drools.FactHandle;
+import org.drools.WorkingMemory;
+
+public class JavaFactRegistryEntry {
+    private WorkingMemory workingMemory;
+    private FactHandle    handle;
+
+    public JavaFactRegistryEntry(final WorkingMemory workingMemory,
+                                 final FactHandle handle) {
+        super();
+        this.workingMemory = workingMemory;
+        this.handle = handle;
+    }
+
+    public FactHandle getFactHandle() {
+        return this.handle;
+    }
+
+    public WorkingMemory getWorkingMemory() {
+        return this.workingMemory;
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/MapGlobalResolver.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/MapGlobalResolver.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/MapGlobalResolver.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,38 @@
+package org.drools.base;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.drools.spi.GlobalResolver;
+
+public class MapGlobalResolver
+    implements
+    GlobalResolver {
+    
+    private static final long serialVersionUID = 400L;
+    
+    private final Map map;
+    
+    public MapGlobalResolver() {
+        this.map = new HashMap();
+    }
+    
+    public MapGlobalResolver(Map map) {
+        this.map = map;
+    }    
+
+    public Object resolveGlobal(String identifier) {
+        return this.map.get( identifier );
+    }
+    
+    public void setGlobal(String identifier, Object value) {
+        this.map.put( identifier,
+                      value );
+    }
+    
+    public Entry[] getGlobals() {
+    	return (Entry[]) this.map.entrySet().toArray(new Entry[this.map.size()]);
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ModifyInterceptor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ModifyInterceptor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ModifyInterceptor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,37 @@
+package org.drools.base;
+
+import java.io.Serializable;
+
+import org.drools.base.mvel.DroolsMVELKnowledgeHelper;
+import org.drools.spi.KnowledgeHelper;
+import org.mvel.ASTNode;
+import org.mvel.ast.WithNode;
+import org.mvel.integration.Interceptor;
+import org.mvel.integration.VariableResolverFactory;
+
+public class ModifyInterceptor
+    implements
+    Interceptor,
+    Serializable {
+    private static final long serialVersionUID = 400L;
+
+    public int doBefore(ASTNode node,
+                        VariableResolverFactory factory) {
+        Object object = ((WithNode) node).getNestedStatement().getValue( null,
+                                                                         factory );
+
+        DroolsMVELKnowledgeHelper resolver = (DroolsMVELKnowledgeHelper) factory.getVariableResolver( "drools" );
+        KnowledgeHelper helper = (KnowledgeHelper) resolver.getValue();
+        helper.modifyRetract( object );
+        return 0;
+    }
+
+    public int doAfter(Object value,
+                       ASTNode node,
+                       VariableResolverFactory factory) {
+        DroolsMVELKnowledgeHelper resolver = (DroolsMVELKnowledgeHelper) factory.getVariableResolver( "drools" );
+        KnowledgeHelper helper = (KnowledgeHelper) resolver.getValue();
+        helper.modifyInsert( value );
+        return 0;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ReferenceOriginalGlobalExporter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ReferenceOriginalGlobalExporter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ReferenceOriginalGlobalExporter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,20 @@
+/**
+ * 
+ */
+package org.drools.base;
+
+import org.drools.WorkingMemory;
+import org.drools.spi.GlobalExporter;
+import org.drools.spi.GlobalResolver;
+
+/**
+ * This implementation does nothing other than pass by reference the original GlobalResolver as used in the StatelessSession.
+ * Care should be taken if you use this strategy, as later executes may change those globals. The GlobalResolver of the StatelessSession
+ * may also not be serialisable friendly.
+ *
+ */
+public class ReferenceOriginalGlobalExporter implements GlobalExporter {       
+    public GlobalResolver export(WorkingMemory workingMemory) {
+        return workingMemory.getGlobalResolver();
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/RuleNameEndsWithAgendaFilter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/RuleNameEndsWithAgendaFilter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/RuleNameEndsWithAgendaFilter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,52 @@
+package org.drools.base;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.Activation;
+import org.drools.spi.AgendaFilter;
+
+/**
+ * Filters activations based on a specified rule name suffix.
+ * 
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris </a>
+ */
+public class RuleNameEndsWithAgendaFilter
+    implements
+    AgendaFilter {
+    private final String  suffix;
+
+    private final boolean accept;
+
+    public RuleNameEndsWithAgendaFilter(final String suffix) {
+        this( suffix,
+              true );
+    }
+
+    public RuleNameEndsWithAgendaFilter(final String suffix,
+                                        final boolean accept) {
+        this.suffix = suffix;
+        this.accept = accept;
+    }
+
+    public boolean accept(final Activation activation) {
+        if ( activation.getRule().getName().endsWith( this.suffix ) ) {
+            return this.accept;
+        } else {
+            return !this.accept;
+        }
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/RuleNameEqualsAgendaFilter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/RuleNameEqualsAgendaFilter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/RuleNameEqualsAgendaFilter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,52 @@
+package org.drools.base;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.Activation;
+import org.drools.spi.AgendaFilter;
+
+/**
+ * Filters activations based on an exact match of a rule name.
+ * 
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris </a>
+ */
+public class RuleNameEqualsAgendaFilter
+    implements
+    AgendaFilter {
+    private final String  name;
+
+    private final boolean accept;
+
+    public RuleNameEqualsAgendaFilter(final String name) {
+        this( name,
+              true );
+    }
+
+    public RuleNameEqualsAgendaFilter(final String name,
+                                      final boolean accept) {
+        this.name = name;
+        this.accept = accept;
+    }
+
+    public boolean accept(final Activation activation) {
+        if ( activation.getRule().getName().equals( this.name ) ) {
+            return this.accept;
+        } else {
+            return !this.accept;
+        }
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/RuleNameMatchesAgendaFilter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/RuleNameMatchesAgendaFilter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/RuleNameMatchesAgendaFilter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,55 @@
+package org.drools.base;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.drools.spi.Activation;
+import org.drools.spi.AgendaFilter;
+
+/**
+ * Filters activations based on a specified regular expression.
+ * 
+ */
+public class RuleNameMatchesAgendaFilter
+    implements
+    AgendaFilter {
+    private final Pattern pattern;
+
+    private final boolean accept;
+
+    public RuleNameMatchesAgendaFilter(final String regexp) {
+        this( regexp,
+              true );
+    }
+
+    public RuleNameMatchesAgendaFilter(final String regexp,
+                                 final boolean accept) {
+        this.pattern = Pattern.compile( regexp );
+        this.accept = accept;
+    }
+
+    public boolean accept(final Activation activation) {
+        Matcher matcher = pattern.matcher( activation.getRule().getName() );
+        if ( matcher.matches() ) {
+            return this.accept;
+        } else {
+            return !this.accept;
+        }
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/RuleNameStartsWithAgendaFilter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/RuleNameStartsWithAgendaFilter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/RuleNameStartsWithAgendaFilter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,52 @@
+package org.drools.base;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.Activation;
+import org.drools.spi.AgendaFilter;
+
+/**
+ * Filters activations based on a specified rule name prefix.
+ * 
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris </a>
+ */
+public class RuleNameStartsWithAgendaFilter
+    implements
+    AgendaFilter {
+    private final String  prefix;
+
+    private final boolean accept;
+
+    public RuleNameStartsWithAgendaFilter(final String prefix) {
+        this( prefix,
+              true );
+    }
+
+    public RuleNameStartsWithAgendaFilter(final String prefix,
+                                          final boolean accept) {
+        this.prefix = prefix;
+        this.accept = accept;
+    }
+
+    public boolean accept(final Activation activation) {
+        if ( activation.getRule().getName().startsWith( this.prefix ) ) {
+            return this.accept;
+        } else {
+            return !this.accept;
+        }
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/SalienceInteger.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/SalienceInteger.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/SalienceInteger.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,33 @@
+package org.drools.base;
+
+import org.drools.WorkingMemory;
+import org.drools.spi.Salience;
+import org.drools.spi.Tuple;
+
+public class SalienceInteger
+    implements
+    Salience {
+    
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    public static final Salience DEFAULT_SALIENCE = new SalienceInteger( 0 );
+    
+    private final int value;
+
+    public SalienceInteger(int value) {
+        this.value = value;
+    }
+
+    public int getValue(final Tuple tuple,
+                        final WorkingMemory workingMemory) {
+        return this.value;
+    }
+    
+    public String toString() {
+        return String.valueOf( this.value );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/SequentialKnowledgeHelper.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/SequentialKnowledgeHelper.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/SequentialKnowledgeHelper.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,182 @@
+package org.drools.base;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.List;
+
+import org.drools.FactException;
+import org.drools.FactHandle;
+import org.drools.QueryResults;
+import org.drools.WorkingMemory;
+import org.drools.common.InternalWorkingMemoryActions;
+import org.drools.rule.Declaration;
+import org.drools.rule.GroupElement;
+import org.drools.rule.Rule;
+import org.drools.spi.Activation;
+import org.drools.spi.AgendaGroup;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.Tuple;
+
+public class SequentialKnowledgeHelper
+    implements
+    KnowledgeHelper {
+
+    private static final long                  serialVersionUID = 400L;
+
+    private Rule                               rule;
+    private GroupElement                       subrule;
+    private Activation                         activation;
+    private Tuple                              tuple;
+    private final InternalWorkingMemoryActions workingMemory;
+
+    public SequentialKnowledgeHelper(final WorkingMemory workingMemory) {
+        this.workingMemory = (InternalWorkingMemoryActions) workingMemory;
+    }
+
+    public void setActivation(final Activation agendaItem) {
+        this.rule = agendaItem.getRule();
+        this.subrule = agendaItem.getSubRule();
+        this.activation = agendaItem;
+        this.tuple = agendaItem.getTuple();
+    }
+    
+    public void reset() {
+        this.rule = null;
+        this.subrule = null;
+        this.activation = null;
+        this.tuple = null;
+    }
+    
+
+    public void insert(final Object object) throws FactException {        
+    }
+    
+    public void insert(final Object object, final long duration) throws FactException {        
+    }
+
+    public void insert(final Object object,
+                       final boolean dynamic) throws FactException {
+    }
+    
+    public void insert(final Object object,
+    				   final long duration,
+    				   final boolean dynamic) throws FactException {
+    }
+
+    public void insertLogical(final Object object) throws FactException {
+    }
+    
+    public void insertLogical(final Object object, final long duration) throws FactException {
+    }
+
+    public void insertLogical(final Object object,
+                              final boolean dynamic) throws FactException {
+    }
+    
+    public void insertLogical(final Object object,
+    						  final long duration,
+            				  final boolean dynamic) throws FactException {
+    }
+
+    public void update(final FactHandle handle,
+                       final Object newObject) throws FactException {
+    }
+
+    public void update(final Object object) throws FactException {
+    }
+
+    public void retract(final FactHandle handle) throws FactException {
+    }
+
+    public void retract(final Object object) throws FactException {
+    }
+
+    public void modifyRetract(final Object object) {
+    }
+
+    public void modifyRetract(final FactHandle factHandle) {
+    }
+
+    public void modifyInsert(final Object object) {
+    }
+
+    public void modifyInsert(final FactHandle factHandle,
+                             final Object object) {      
+    }
+
+    public Rule getRule() {
+        return this.rule;
+    }
+
+    //    public List getObjects() {
+    //        return null; //this.workingMemory.getObjects();
+    //    }
+    //
+    //    public List getObjects(final Class objectClass) {
+    //        return null; //this.workingMemory.getObjects( objectClass );
+    //    }
+    //
+    //    public void clearAgenda() {
+    //        this.workingMemory.clearAgenda();
+    //    }
+    //
+    //    public void clearAgendaGroup(final String group) {
+    //        this.workingMemory.clearAgendaGroup( group );
+    //    }
+
+
+    public Tuple getTuple() {
+        return this.tuple;
+    }
+
+    public WorkingMemory getWorkingMemory() {
+        return this.workingMemory;
+    }
+
+    public Activation getActivation() {
+        return this.activation;
+    }
+
+    //    public QueryResults getQueryResults(final String query) {
+    //        return this.workingMemory.getQueryResults( query );
+    //    }
+    //
+    //    public AgendaGroup getFocus() {
+    //        return this.workingMemory.getFocus();
+    //    }
+    //
+    public void setFocus(final String focus) {
+        this.workingMemory.setFocus( focus );
+    }
+
+    //
+    //    public void setFocus(final AgendaGroup focus) {
+    //        this.workingMemory.setFocus( focus );
+    //    }
+    
+    public Object get(final Declaration declaration) {
+        return declaration.getValue( workingMemory, this.tuple.get( declaration ).getObject() );
+    }    
+
+    public Declaration getDeclaration(final String identifier) {
+        return (Declaration) this.subrule.getOuterDeclarations().get( identifier );
+    }
+    
+    public void halt() {
+        this.workingMemory.halt();
+    }    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ShadowProxy.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ShadowProxy.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ShadowProxy.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.base;
+
+/**
+ * A markup interface for shadow fact proxies
+ */
+public interface ShadowProxy {
+
+    public void updateProxy();
+
+    public Object getShadowedObject();
+    
+    public void setShadowedObject(Object object);
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ShadowProxyFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ShadowProxyFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ShadowProxyFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,1374 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.base;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.asm.ClassWriter;
+import org.drools.asm.FieldVisitor;
+import org.drools.asm.Label;
+import org.drools.asm.MethodVisitor;
+import org.drools.asm.Opcodes;
+import org.drools.asm.Type;
+import org.drools.util.ShadowProxyUtils;
+
+/**
+ * A factory for ShadowProxy classes
+ */
+public class ShadowProxyFactory {
+    private static final String           UPDATE_PROXY         = "updateProxy";
+    private static final String           SET_SHADOWED_OBJECT  = "setShadowedObject";
+    private static final String           GET_SHADOWED_OBJECT  = "getShadowedObject";
+
+    private static final String           BASE_INTERFACE       = Type.getInternalName( ShadowProxy.class );
+
+    //private static final String FIELD_NAME_PREFIX   = "__";
+
+    public static final String            FIELD_SET_FLAG       = "IsSet";
+
+    public static final String            DELEGATE_FIELD_NAME  = "delegate";
+
+    public static final String            HASHCACHE_FIELD_NAME = "__hashCache";
+
+    private static final ProtectionDomain PROTECTION_DOMAIN;
+
+    static {
+        PROTECTION_DOMAIN = (ProtectionDomain) AccessController.doPrivileged( new PrivilegedAction() {
+            public Object run() {
+                return ShadowProxyFactory.class.getProtectionDomain();
+            }
+        } );
+    }
+
+    public static Class getProxy(final Class clazz) {
+        try {
+            if ( !isPossibleToGenerateTheProxyFor( clazz ) ) {
+                return null;
+            }
+
+            final String className = getInternalProxyClassNameForClass( clazz );
+            // generating byte array to create target class
+            final byte[] bytes = dump( clazz,
+                                       className );
+            // use bytes to get a class 
+            final ByteArrayClassLoader classLoader = new ByteArrayClassLoader( Thread.currentThread().getContextClassLoader() );
+            final Class newClass = classLoader.defineClass( className.replace( '/',
+                                                                               '.' ),
+                                                            bytes,
+                                                            PROTECTION_DOMAIN );
+            return newClass;
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( e );
+        }
+    }
+
+    public static byte[] getProxyBytes(final Class clazz) {
+        try {
+            if ( !isPossibleToGenerateTheProxyFor( clazz ) ) {
+                return null;
+            }
+
+            final String className = getInternalProxyClassNameForClass( clazz );
+            // generating byte array to create target class
+            final byte[] bytes = dump( clazz,
+                                       className );
+            return bytes;
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( e );
+        }
+    }
+
+    protected static boolean isPossibleToGenerateTheProxyFor(final Class clazz) throws Exception {
+        if ( (clazz.getModifiers() & Modifier.FINAL) != 0 ) {
+            return false;
+        }
+        try {
+            Method equals = clazz.getMethod( "equals",
+                                             new Class[]{Object.class} );
+            if ( Modifier.isFinal( equals.getModifiers() ) ) {
+                return false;
+            }
+        } catch ( NoSuchMethodException e ) {
+            // that's fine
+        }
+        try {
+            Method hashcode = clazz.getMethod( "hashCode",
+                                               new Class[0] );
+            if ( Modifier.isFinal( hashcode.getModifiers() ) ) {
+                return false;
+            }
+        } catch ( NoSuchMethodException e ) {
+            // that's fine
+        }
+        return true;
+    }
+
+    /**
+     * @param clazz
+     * @return
+     */
+    public static String getInternalProxyClassNameForClass(final Class clazz) {
+        String className = null;
+        if ( clazz.getPackage() != null && (clazz.getPackage().getName().startsWith( "java." ) || clazz.getPackage().getName().startsWith( "javax." )) ) {
+            className = "org/drools/shadow/" + Type.getInternalName( clazz ) + "ShadowProxy";
+        } else {
+            className = Type.getInternalName( clazz ) + "ShadowProxy";
+        }
+        return className;
+    }
+
+    public static String getProxyClassNameForClass(final Class clazz) {
+        String className = null;
+        Package pkg = clazz.getPackage();
+        if ( pkg != null && (pkg.getName().startsWith( "java." ) || pkg.getName().startsWith( "javax." )) ) {
+            className = "org.drools.shadow." + clazz.getName() + "ShadowProxy";
+        } else {
+            className = clazz.getName() + "ShadowProxy";
+        }
+        return className;
+    }
+
+    protected static byte[] dump(final Class clazz,
+                                 final String className) throws Exception {
+
+        final ClassWriter cw = new ClassWriter( true );
+
+        buildClassHeader( clazz,
+                          className,
+                          cw );
+
+        buildConstructor( clazz,
+                          className,
+                          cw );
+
+        buildField( ShadowProxyFactory.DELEGATE_FIELD_NAME,
+                    Type.getDescriptor( clazz ),
+                    cw );
+
+        final Method getShadowed = ShadowProxy.class.getDeclaredMethod( GET_SHADOWED_OBJECT,
+                                                                        new Class[]{} );
+        final Method setShadowed = ShadowProxy.class.getDeclaredMethod( SET_SHADOWED_OBJECT,
+                                                                        new Class[]{Object.class} );
+        buildSimpleGetMethod( ShadowProxyFactory.DELEGATE_FIELD_NAME,
+                              clazz,
+                              getShadowed,
+                              className,
+                              clazz,
+                              cw );
+
+        buildSetShadowedObject( clazz,
+                                className,
+                                setShadowed,
+                                cw );
+
+        if ( Collection.class.isAssignableFrom( clazz ) ) {
+            buildCollectionClass( clazz,
+                                  className,
+                                  cw );
+        } else if ( Map.class.isAssignableFrom( clazz ) ) {
+            buildMapClass( clazz,
+                           className,
+                           cw );
+        } else {
+            buildRegularClass( clazz,
+                               className,
+                               cw );
+        }
+
+        return cw.toByteArray();
+    }
+
+    private static void buildCollectionClass(final Class clazz,
+                                             final String className,
+                                             final ClassWriter cw) {
+
+        buildCollectionUpdateProxyMethod( clazz,
+                                          className,
+                                          cw );
+
+    }
+
+    private static void buildMapClass(final Class clazz,
+                                      final String className,
+                                      final ClassWriter cw) {
+
+        buildMapUpdateProxyMethod( clazz,
+                                   className,
+                                   cw );
+
+    }
+
+    private static void buildRegularClass(final Class clazz,
+                                          final String className,
+                                          final ClassWriter cw) {
+        final Map fieldTypes = new HashMap();
+        final Method[] methods = getMethods( clazz );
+        for ( int i = 0; i < methods.length; i++ ) {
+            if ( (!Modifier.isFinal( methods[i].getModifiers() )) && Modifier.isPublic( methods[i].getModifiers() ) && (!Modifier.isStatic( methods[i].getModifiers() )) ) {
+                if ( (!methods[i].getReturnType().equals( Void.TYPE )) && (methods[i].getParameterTypes().length == 0) && (!methods[i].getName().equals( "hashCode" )) && (!methods[i].getName().equals( "toString" )) ) {
+
+                    final String fieldName = methods[i].getName();
+
+                    buildField( fieldName,
+                                Type.getDescriptor( methods[i].getReturnType() ),
+                                cw );
+                    fieldTypes.put( fieldName,
+                                    methods[i] );
+
+                    buildField( fieldName + ShadowProxyFactory.FIELD_SET_FLAG,
+                                Type.BOOLEAN_TYPE.getDescriptor(),
+                                cw );
+                    buildGetMethod( fieldName,
+                                    methods[i].getReturnType(),
+                                    fieldName + ShadowProxyFactory.FIELD_SET_FLAG,
+                                    methods[i],
+                                    className,
+                                    clazz,
+                                    cw );
+                } else if ( (!methods[i].getName().equals( "hashCode" )) && (!methods[i].getName().equals( "equals" )) ) {
+                    buildDelegateMethod( methods[i],
+                                         clazz,
+                                         className,
+                                         cw );
+                }
+            }
+        }
+
+        buildUpdateProxyMethod( fieldTypes,
+                                className,
+                                cw );
+
+        buildEquals( cw,
+                     className,
+                     clazz,
+                     fieldTypes );
+
+        buildField( ShadowProxyFactory.HASHCACHE_FIELD_NAME,
+                    Type.getDescriptor( int.class ),
+                    cw );
+
+        buildHashCode( cw,
+                       className,
+                       clazz,
+                       fieldTypes );
+    }
+
+    /**
+     * Filter out any method we are not interested in
+     * @param clazz
+     * @return
+     */
+    private static Method[] getMethods(final Class clazz) {
+        // to help filtering process, we will create a map of maps:
+        // Map< String methodName, Map< Class[] parameterTypes, Method method > >
+        final Map map = new HashMap();
+        final List helperList = new ArrayList();
+        final Method[] methods = clazz.getMethods();
+        for ( int i = 0; i < methods.length; i++ ) {
+            Method previous = null;
+            Map signatures = (Map) map.get( methods[i].getName() );
+            final ParametersWrapper key = new ParametersWrapper( methods[i].getParameterTypes() );
+            if ( signatures != null ) {
+                previous = (Method) signatures.get( key );
+            }
+            // if no previous method with the same name and parameter types is found
+            // or if the previous method's return type is a super class of the 
+            // current method's return type, add current to the map
+            // overriding previous if it exists
+            if ( (previous == null) || (previous.getReturnType().isAssignableFrom( methods[i].getReturnType() )) ) {
+                if ( signatures == null ) {
+                    signatures = new HashMap();
+                    map.put( methods[i].getName(),
+                             signatures );
+                }
+                if ( signatures.put( key,
+                                     methods[i] ) != null ) {
+                    helperList.remove( previous );
+                }
+                helperList.add( methods[i] );
+            }
+        }
+        return (Method[]) helperList.toArray( new Method[helperList.size()] );
+    }
+
+    private static class ParametersWrapper {
+        private Class[] parameters;
+
+        public ParametersWrapper(final Class[] parameters) {
+            this.parameters = parameters;
+        }
+
+        public int hashCode() {
+            return this.parameters.length;
+        }
+
+        public boolean equals(final Object o) {
+            if ( !(o instanceof ParametersWrapper) ) {
+                return false;
+            }
+            final ParametersWrapper other = (ParametersWrapper) o;
+
+            if ( this.parameters.length != other.parameters.length ) {
+                return false;
+            }
+
+            for ( int i = 0; i < this.parameters.length; i++ ) {
+                if ( !this.parameters[i].equals( other.parameters[i] ) ) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Builds the shadow proxy class header
+     *  
+     * @param clazz The class to build shadow proxy for
+     * @param className The shadow proxy class name
+     * @param cw
+     */
+    protected static void buildClassHeader(final Class clazz,
+                                           final String className,
+                                           final ClassWriter cw) {
+        if ( clazz.isInterface() ) {
+            cw.visit( Opcodes.V1_5,
+                      Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER,
+                      className,
+                      null,
+                      Type.getInternalName( Object.class ),
+                      new String[]{ShadowProxyFactory.BASE_INTERFACE, Type.getInternalName( clazz )} );
+        } else {
+            cw.visit( Opcodes.V1_5,
+                      Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER,
+                      className,
+                      null,
+                      Type.getInternalName( clazz ),
+                      new String[]{ShadowProxyFactory.BASE_INTERFACE} );
+        }
+
+        cw.visitSource( null,
+                        null );
+    }
+
+    /**
+     * Creates the field defined by the given FieldDefinition 
+     * 
+     * @param cw
+     * @param fieldDef
+     */
+    protected static void buildField(final String name,
+                                     final String type,
+                                     final ClassWriter cw) {
+        FieldVisitor fv;
+        fv = cw.visitField( Opcodes.ACC_PRIVATE,
+                            name,
+                            type,
+                            null,
+                            null );
+        fv.visitEnd();
+    }
+
+    /**
+     * Creates a constructor for the shadow proxy receiving
+     * the actual delegate class as parameter
+     * 
+     * @param originalClassName
+     * @param className
+     * @param cw
+     */
+    private static void buildConstructor(final Class clazz,
+                                         final String className,
+                                         final ClassWriter cw) {
+        MethodVisitor mv;
+        {
+            mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+                                 "<init>",
+                                 Type.getMethodDescriptor( Type.VOID_TYPE,
+                                                           new Type[]{Type.getType( clazz )} ),
+                                 null,
+                                 null );
+            mv.visitCode();
+
+            // super();
+            final Label l0 = new Label();
+            mv.visitLabel( l0 );
+            mv.visitLineNumber( 41,
+                                l0 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             0 );
+            if ( clazz.isInterface() ) {
+                mv.visitMethodInsn( Opcodes.INVOKESPECIAL,
+                                    Type.getInternalName( Object.class ),
+                                    "<init>",
+                                    Type.getMethodDescriptor( Type.VOID_TYPE,
+                                                              new Type[]{} ) );
+            } else {
+                mv.visitMethodInsn( Opcodes.INVOKESPECIAL,
+                                    Type.getInternalName( clazz ),
+                                    "<init>",
+                                    Type.getMethodDescriptor( Type.VOID_TYPE,
+                                                              new Type[]{} ) );
+            }
+
+            // this.delegate = delegate
+            final Label l1 = new Label();
+            mv.visitLabel( l1 );
+            mv.visitLineNumber( 42,
+                                l1 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             0 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             1 );
+            mv.visitFieldInsn( Opcodes.PUTFIELD,
+                               className,
+                               ShadowProxyFactory.DELEGATE_FIELD_NAME,
+                               Type.getDescriptor( clazz ) );
+
+            // return
+            final Label l2 = new Label();
+            mv.visitLabel( l2 );
+            mv.visitLineNumber( 43,
+                                l2 );
+            mv.visitInsn( Opcodes.RETURN );
+
+            final Label l3 = new Label();
+            mv.visitLabel( l3 );
+            mv.visitLocalVariable( "this",
+                                   "L" + className + ";",
+                                   null,
+                                   l0,
+                                   l3,
+                                   0 );
+            mv.visitLocalVariable( ShadowProxyFactory.DELEGATE_FIELD_NAME,
+                                   Type.getDescriptor( clazz ),
+                                   null,
+                                   l0,
+                                   l3,
+                                   1 );
+            mv.visitMaxs( 0,
+                          0 );
+            mv.visitEnd();
+        }
+    }
+
+    /**
+     * Creates the proxy reader method for the given method
+     * 
+     * @param fieldName
+     * @param fieldFlag
+     * @param method
+     * @param cw
+     */
+    protected static void buildGetMethod(final String fieldName,
+                                         final Class fieldType,
+                                         final String fieldFlag,
+                                         final Method method,
+                                         final String className,
+                                         final Class clazz,
+                                         final ClassWriter cw) {
+        // method signature 
+        final Class[] exceptionTypes = method.getExceptionTypes();
+        final String[] exceptions = getExceptionArrayAsString( exceptionTypes );
+        final MethodVisitor mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+                                                 method.getName(),
+                                                 Type.getMethodDescriptor( method ),
+                                                 null,
+                                                 exceptions );
+        mv.visitCode();
+
+        // if ( ! _fieldIsSet ) {
+        final Label l0 = new Label();
+        mv.visitLabel( l0 );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         0 );
+        mv.visitFieldInsn( Opcodes.GETFIELD,
+                           className,
+                           fieldFlag,
+                           Type.BOOLEAN_TYPE.getDescriptor() );
+        final Label l1 = new Label();
+        mv.visitJumpInsn( Opcodes.IFNE,
+                          l1 );
+
+        //     __fieldIsSet = true;
+        final Label l3 = new Label();
+        mv.visitLabel( l3 );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         0 );
+        mv.visitInsn( Opcodes.ICONST_1 );
+        mv.visitFieldInsn( Opcodes.PUTFIELD,
+                           className,
+                           fieldFlag,
+                           Type.BOOLEAN_TYPE.getDescriptor() );
+
+        if ( Map.class.isAssignableFrom( fieldType ) || Collection.class.isAssignableFrom( fieldType ) || fieldType.isArray() ) {
+
+            // FieldType aux = this.delegate.getField();
+            Label l01 = new Label();
+            mv.visitLabel( l01 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             0 );
+            mv.visitFieldInsn( Opcodes.GETFIELD,
+                               className,
+                               DELEGATE_FIELD_NAME,
+                               Type.getDescriptor( clazz ) );
+            if ( clazz.isInterface() ) {
+                mv.visitMethodInsn( Opcodes.INVOKEINTERFACE,
+                                    Type.getInternalName( clazz ),
+                                    method.getName(),
+                                    Type.getMethodDescriptor( method ) );
+            } else {
+                mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                                    Type.getInternalName( clazz ),
+                                    method.getName(),
+                                    Type.getMethodDescriptor( method ) );
+            }
+            mv.visitVarInsn( Opcodes.ASTORE,
+                             1 );
+
+            // this.field = (FieldType) ShadoProxyUtils.clone( aux );
+            Label l11 = new Label();
+            mv.visitLabel( l11 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             0 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             1 );
+            mv.visitMethodInsn( Opcodes.INVOKESTATIC,
+                                Type.getInternalName( ShadowProxyUtils.class ),
+                                "cloneObject",
+                                "(Ljava/lang/Object;)Ljava/lang/Object;" );
+            mv.visitTypeInsn( Opcodes.CHECKCAST,
+                              Type.getInternalName( fieldType ) );
+            mv.visitFieldInsn( Opcodes.PUTFIELD,
+                               className,
+                               fieldName,
+                               Type.getDescriptor( fieldType ) );
+
+        } else {
+            //     __field = this.delegate.method();
+            final Label l2 = new Label();
+            mv.visitLabel( l2 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             0 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             0 );
+            mv.visitFieldInsn( Opcodes.GETFIELD,
+                               className,
+                               ShadowProxyFactory.DELEGATE_FIELD_NAME,
+                               Type.getDescriptor( clazz ) );
+            if ( clazz.isInterface() ) {
+                mv.visitMethodInsn( Opcodes.INVOKEINTERFACE,
+                                    Type.getInternalName( clazz ),
+                                    method.getName(),
+                                    Type.getMethodDescriptor( method ) );
+            } else {
+                mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                                    Type.getInternalName( clazz ),
+                                    method.getName(),
+                                    Type.getMethodDescriptor( method ) );
+            }
+            mv.visitFieldInsn( Opcodes.PUTFIELD,
+                               className,
+                               fieldName,
+                               Type.getDescriptor( fieldType ) );
+
+        }
+
+        // }
+        // return __field;
+        mv.visitLabel( l1 );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         0 );
+        mv.visitFieldInsn( Opcodes.GETFIELD,
+                           className,
+                           fieldName,
+                           Type.getDescriptor( fieldType ) );
+        mv.visitInsn( Type.getType( fieldType ).getOpcode( Opcodes.IRETURN ) );
+
+        // local variables table
+        final Label l4 = new Label();
+        mv.visitLabel( l4 );
+        mv.visitLocalVariable( "this",
+                               "L" + className + ";",
+                               null,
+                               l0,
+                               l4,
+                               0 );
+        mv.visitMaxs( 0,
+                      0 );
+        mv.visitEnd();
+    }
+
+    /**
+     * Creates the proxy reader method for the given method
+     * 
+     * @param fieldName
+     * @param fieldFlag
+     * @param method
+     * @param cw
+     */
+    protected static void buildSimpleGetMethod(final String fieldName,
+                                               final Class fieldType,
+                                               final Method method,
+                                               final String className,
+                                               final Class clazz,
+                                               final ClassWriter cw) {
+
+        final Class[] exceptionTypes = method.getExceptionTypes();
+        final String[] exceptions = getExceptionArrayAsString( exceptionTypes );
+        // method signature 
+        final MethodVisitor mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+                                                 method.getName(),
+                                                 Type.getMethodDescriptor( method ),
+                                                 null,
+                                                 exceptions );
+        mv.visitCode();
+
+        // return __field;
+        final Label l0 = new Label();
+        mv.visitLabel( l0 );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         0 );
+        mv.visitFieldInsn( Opcodes.GETFIELD,
+                           className,
+                           fieldName,
+                           Type.getDescriptor( fieldType ) );
+        mv.visitInsn( Type.getType( fieldType ).getOpcode( Opcodes.IRETURN ) );
+
+        // local variables table
+        final Label l4 = new Label();
+        mv.visitLabel( l4 );
+        mv.visitLocalVariable( "this",
+                               "L" + className + ";",
+                               null,
+                               l0,
+                               l4,
+                               0 );
+        mv.visitMaxs( 0,
+                      0 );
+        mv.visitEnd();
+    }
+
+    protected static void buildUpdateProxyMethod(final Map fieldTypes,
+                                                 final String className,
+                                                 final ClassWriter cw) {
+        final MethodVisitor mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+                                                 ShadowProxyFactory.UPDATE_PROXY,
+                                                 Type.getMethodDescriptor( Type.VOID_TYPE,
+                                                                           new Type[]{} ),
+                                                 null,
+                                                 null );
+        mv.visitCode();
+        final Label l0 = new Label();
+        mv.visitLabel( l0 );
+        for ( final Iterator it = fieldTypes.entrySet().iterator(); it.hasNext(); ) {
+            final Map.Entry entry = (Map.Entry) it.next();
+            final String fieldName = (String) entry.getKey();
+            final String fieldFlag = fieldName + ShadowProxyFactory.FIELD_SET_FLAG;
+            final Class fieldType = ((Method) entry.getValue()).getReturnType();
+            final Label l1 = new Label();
+            mv.visitLabel( l1 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             0 );
+            if ( fieldType.isPrimitive() ) {
+                if ( fieldType.equals( Long.TYPE ) ) {
+                    mv.visitInsn( Opcodes.LCONST_0 );
+                } else if ( fieldType.equals( Double.TYPE ) ) {
+                    mv.visitInsn( Opcodes.DCONST_0 );
+                } else if ( fieldType.equals( Float.TYPE ) ) {
+                    mv.visitInsn( Opcodes.FCONST_0 );
+                } else {
+                    mv.visitInsn( Opcodes.ICONST_0 );
+                }
+            } else {
+                mv.visitInsn( Opcodes.ACONST_NULL );
+            }
+            mv.visitFieldInsn( Opcodes.PUTFIELD,
+                               className,
+                               fieldName,
+                               Type.getDescriptor( fieldType ) );
+            final Label l2 = new Label();
+            mv.visitLabel( l2 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             0 );
+            mv.visitInsn( Opcodes.ICONST_0 );
+            mv.visitFieldInsn( Opcodes.PUTFIELD,
+                               className,
+                               fieldFlag,
+                               Type.BOOLEAN_TYPE.getDescriptor() );
+        }
+
+        //    this.__hashCache = 0;
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         0 );
+        mv.visitInsn( Opcodes.ICONST_0 );
+        mv.visitFieldInsn( Opcodes.PUTFIELD,
+                           className,
+                           ShadowProxyFactory.HASHCACHE_FIELD_NAME,
+                           Type.getDescriptor( int.class ) );
+
+        final Label l4 = new Label();
+        mv.visitLabel( l4 );
+        mv.visitInsn( Opcodes.RETURN );
+        final Label l5 = new Label();
+        mv.visitLabel( l5 );
+        mv.visitLocalVariable( "this",
+                               "L" + className + ";",
+                               null,
+                               l0,
+                               l5,
+                               0 );
+        mv.visitMaxs( 0,
+                      0 );
+        mv.visitEnd();
+    }
+
+    protected static void buildSetShadowedObject(final Class clazz,
+                                                 final String className,
+                                                 final Method setShadowed,
+                                                 final ClassWriter cw) {
+        final MethodVisitor mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+                                                 setShadowed.getName(),
+                                                 Type.getMethodDescriptor( setShadowed ),
+                                                 null,
+                                                 null );
+        mv.visitCode();
+        Label l0 = new Label();
+        mv.visitLabel( l0 );
+        // this.delegate = (<clazz>) object;
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         0 );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         1 );
+        mv.visitTypeInsn( Opcodes.CHECKCAST,
+                          Type.getInternalName( clazz ) );
+        mv.visitFieldInsn( Opcodes.PUTFIELD,
+                           className,
+                           DELEGATE_FIELD_NAME,
+                           Type.getDescriptor( clazz ) );
+        if ( Collection.class.isAssignableFrom( clazz ) || Map.class.isAssignableFrom( clazz ) ) {
+            Label l1 = new Label();
+            mv.visitLabel( l1 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             0 );
+            mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                                className,
+                                UPDATE_PROXY,
+                                Type.getMethodDescriptor( Type.VOID_TYPE,
+                                                          new Type[0] ) );
+        }
+        Label l2 = new Label();
+        mv.visitLabel( l2 );
+        mv.visitInsn( Opcodes.RETURN );
+        Label l3 = new Label();
+        mv.visitLabel( l3 );
+        mv.visitLocalVariable( "this",
+                               "L" + className + ";",
+                               null,
+                               l0,
+                               l3,
+                               0 );
+        mv.visitLocalVariable( "object",
+                               Type.getDescriptor( Object.class ),
+                               null,
+                               l0,
+                               l3,
+                               1 );
+        mv.visitMaxs( 0,
+                      0 );
+        mv.visitEnd();
+    }
+
+    /**
+     * Creates an update proxy method for Map classes
+     * 
+     * public void updateProxy() {
+     *     this.clear();
+     *     this.addAll( this.delegate );
+     * }
+     * 
+     * @param clazz
+     * @param className
+     * @param cw
+     */
+    protected static void buildCollectionUpdateProxyMethod(final Class clazz,
+                                                           final String className,
+                                                           final ClassWriter cw) {
+        final MethodVisitor mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+                                                 ShadowProxyFactory.UPDATE_PROXY,
+                                                 Type.getMethodDescriptor( Type.VOID_TYPE,
+                                                                           new Type[]{} ),
+                                                 null,
+                                                 null );
+        mv.visitCode();
+        final Label l0 = new Label();
+        mv.visitLabel( l0 );
+        // this.clear();
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         0 );
+        mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                            className,
+                            "clear",
+                            Type.getMethodDescriptor( Type.VOID_TYPE,
+                                                      new Type[0] ) );
+        Label l1 = new Label();
+        mv.visitLabel( l1 );
+        // this.addAll( this.delegate );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         0 );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         0 );
+        mv.visitFieldInsn( Opcodes.GETFIELD,
+                           className,
+                           DELEGATE_FIELD_NAME,
+                           Type.getDescriptor( clazz ) );
+        mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                            className,
+                            "addAll",
+                            Type.getMethodDescriptor( Type.BOOLEAN_TYPE,
+                                                      new Type[]{Type.getType( Collection.class )} ) );
+        mv.visitInsn( Opcodes.POP );
+        Label l2 = new Label();
+        mv.visitLabel( l2 );
+        mv.visitInsn( Opcodes.RETURN );
+        Label l3 = new Label();
+        mv.visitLabel( l3 );
+        mv.visitLocalVariable( "this",
+                               "L" + className + ";",
+                               null,
+                               l0,
+                               l3,
+                               0 );
+        mv.visitMaxs( 0,
+                      0 );
+        mv.visitEnd();
+    }
+
+    /**
+     * Creates an update proxy method for Map classes
+     * 
+     * public void updateProxy() {
+     *     this.clear();
+     *     this.putAll( this.delegate );
+     * }
+     * 
+     * @param clazz
+     * @param className
+     * @param cw
+     */
+    protected static void buildMapUpdateProxyMethod(final Class clazz,
+                                                    final String className,
+                                                    final ClassWriter cw) {
+        final MethodVisitor mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+                                                 ShadowProxyFactory.UPDATE_PROXY,
+                                                 Type.getMethodDescriptor( Type.VOID_TYPE,
+                                                                           new Type[]{} ),
+                                                 null,
+                                                 null );
+        mv.visitCode();
+        final Label l0 = new Label();
+        mv.visitLabel( l0 );
+        // this.clear();
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         0 );
+        mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                            className,
+                            "clear",
+                            Type.getMethodDescriptor( Type.VOID_TYPE,
+                                                      new Type[0] ) );
+        Label l1 = new Label();
+        mv.visitLabel( l1 );
+        // this.putAll( this.delegate );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         0 );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         0 );
+        mv.visitFieldInsn( Opcodes.GETFIELD,
+                           className,
+                           DELEGATE_FIELD_NAME,
+                           Type.getDescriptor( clazz ) );
+        mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                            className,
+                            "putAll",
+                            Type.getMethodDescriptor( Type.VOID_TYPE,
+                                                      new Type[]{Type.getType( Map.class )} ) );
+        Label l2 = new Label();
+        mv.visitLabel( l2 );
+        mv.visitInsn( Opcodes.RETURN );
+        Label l3 = new Label();
+        mv.visitLabel( l3 );
+        mv.visitLocalVariable( "this",
+                               "L" + className + ";",
+                               null,
+                               l0,
+                               l3,
+                               0 );
+        mv.visitMaxs( 0,
+                      0 );
+        mv.visitEnd();
+    }
+
+    protected static void buildDelegateMethod(final Method method,
+                                              final Class clazz,
+                                              final String className,
+                                              final ClassWriter cw) {
+
+        // creating method visitor
+        final String[] exceptions = getExceptionArrayAsString( method.getExceptionTypes() );
+        final MethodVisitor mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+                                                 method.getName(),
+                                                 Type.getMethodDescriptor( method ),
+                                                 null,
+                                                 exceptions );
+        mv.visitCode();
+
+        // return this.delegate.method(...);
+        final Label l0 = new Label();
+        mv.visitLabel( l0 );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         0 );
+        mv.visitFieldInsn( Opcodes.GETFIELD,
+                           className,
+                           ShadowProxyFactory.DELEGATE_FIELD_NAME,
+                           Type.getDescriptor( clazz ) );
+
+        final Class[] parameters = method.getParameterTypes();
+        for ( int i = 0, offset = 1; i < parameters.length; i++ ) {
+            Type type = Type.getType( parameters[i] );
+            mv.visitVarInsn( type.getOpcode( Opcodes.ILOAD ),
+                             offset );
+            offset += type.getSize();
+        }
+        if ( clazz.isInterface() ) {
+            mv.visitMethodInsn( Opcodes.INVOKEINTERFACE,
+                                Type.getInternalName( clazz ),
+                                method.getName(),
+                                Type.getMethodDescriptor( method ) );
+        } else {
+            mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                                Type.getInternalName( clazz ),
+                                method.getName(),
+                                Type.getMethodDescriptor( method ) );
+        }
+        mv.visitInsn( Type.getType( method.getReturnType() ).getOpcode( Opcodes.IRETURN ) );
+        final Label l1 = new Label();
+        mv.visitLabel( l1 );
+        mv.visitLocalVariable( "this",
+                               "L" + className + ";",
+                               null,
+                               l0,
+                               l1,
+                               0 );
+        for ( int i = 0, offset = 0; i < parameters.length; i++ ) {
+            mv.visitLocalVariable( "arg" + i,
+                                   Type.getDescriptor( parameters[i] ),
+                                   null,
+                                   l0,
+                                   l1,
+                                   offset );
+            offset += Type.getType( parameters[i] ).getSize();
+        }
+        mv.visitMaxs( 0,
+                      0 );
+        mv.visitEnd();
+    }
+
+    protected static void buildEquals(final ClassWriter cw,
+                                      final String className,
+                                      final Class clazz,
+                                      final Map fieldTypes) {
+        MethodVisitor mv;
+        // Building equals method
+        {
+            mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+                                 "equals",
+                                 Type.getMethodDescriptor( Type.BOOLEAN_TYPE,
+                                                           new Type[]{Type.getType( Object.class )} ),
+                                 null,
+                                 null );
+            mv.visitCode();
+            final Label l0 = new Label();
+            mv.visitLabel( l0 );
+
+            // if ( this == object || this.delegate == object || this.delegate.equals( object ) ) {
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             0 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             1 );
+            final Label l1 = new Label();
+            mv.visitJumpInsn( Opcodes.IF_ACMPEQ,
+                              l1 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             0 );
+            mv.visitFieldInsn( Opcodes.GETFIELD,
+                               className,
+                               DELEGATE_FIELD_NAME,
+                               Type.getDescriptor( clazz ) );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             1 );
+            mv.visitJumpInsn( Opcodes.IF_ACMPEQ,
+                              l1 );
+            
+            mv.visitVarInsn(Opcodes.ALOAD, 0);
+            mv.visitFieldInsn( Opcodes.GETFIELD,
+                               className,
+                               DELEGATE_FIELD_NAME,
+                               Type.getDescriptor( clazz ) );
+            mv.visitVarInsn(Opcodes.ALOAD, 1);
+            if ( clazz.isInterface() ) {
+                mv.visitMethodInsn( Opcodes.INVOKEINTERFACE,
+                                    Type.getInternalName( clazz ),
+                                    "equals",
+                                    Type.getMethodDescriptor( Type.BOOLEAN_TYPE,
+                                                              new Type[]{Type.getType( Object.class )} ) );
+            } else {
+                mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                                    Type.getInternalName( clazz ),
+                                    "equals",
+                                    Type.getMethodDescriptor( Type.BOOLEAN_TYPE,
+                                                              new Type[]{Type.getType( Object.class )} ) );
+            }
+            Label l2 = new Label();
+            mv.visitJumpInsn(Opcodes.IFEQ, l2);
+            
+            //      return true;
+            mv.visitLabel( l1 );
+            mv.visitInsn( Opcodes.ICONST_1 );
+            mv.visitInsn( Opcodes.IRETURN );
+            mv.visitLabel( l2 );
+
+            // if (( object == null ) || ( ! ( object instanceof <class> ) ) ) 
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             1 );
+            final Label l3 = new Label();
+            mv.visitJumpInsn( Opcodes.IFNULL,
+                              l3 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             1 );
+            mv.visitTypeInsn( Opcodes.INSTANCEOF,
+                              Type.getInternalName( clazz ) );
+            final Label l4 = new Label();
+            mv.visitJumpInsn( Opcodes.IFNE,
+                              l4 );
+
+            //       return false;
+            mv.visitLabel( l3 );
+            mv.visitInsn( Opcodes.ICONST_0 );
+            mv.visitInsn( Opcodes.IRETURN );
+            mv.visitLabel( l4 );
+
+            // if( object instanceof ShadowProxy && 
+            //     ( this.delegate == ((ShadowProxy)object).delegate ||
+            //       this.delegate.equals( ((ShadowProxy)object).delegate ) ) ) {
+            Label c0 = new Label();
+            mv.visitLabel( c0 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             1 );
+            mv.visitTypeInsn( Opcodes.INSTANCEOF,
+                              className );
+            Label c1 = new Label();
+            mv.visitJumpInsn( Opcodes.IFEQ,
+                              c1 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             0 );
+            mv.visitFieldInsn( Opcodes.GETFIELD,
+                               className,
+                               DELEGATE_FIELD_NAME,
+                               Type.getDescriptor( clazz ) );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             1 );
+            mv.visitTypeInsn( Opcodes.CHECKCAST,
+                              className );
+            mv.visitFieldInsn( Opcodes.GETFIELD,
+                               className,
+                               DELEGATE_FIELD_NAME,
+                               Type.getDescriptor( clazz ) );
+            Label c2 = new Label();
+            mv.visitJumpInsn( Opcodes.IF_ACMPEQ,
+                              c2 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             0 );
+            mv.visitFieldInsn( Opcodes.GETFIELD,
+                               className,
+                               DELEGATE_FIELD_NAME,
+                               Type.getDescriptor( clazz ) );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             1 );
+            mv.visitTypeInsn( Opcodes.CHECKCAST,
+                              className );
+            mv.visitFieldInsn( Opcodes.GETFIELD,
+                               className,
+                               DELEGATE_FIELD_NAME,
+                               Type.getDescriptor( clazz ) );
+            if ( clazz.isInterface() ) {
+                mv.visitMethodInsn( Opcodes.INVOKEINTERFACE,
+                                    Type.getInternalName( clazz ),
+                                    "equals",
+                                    Type.getMethodDescriptor( Type.BOOLEAN_TYPE,
+                                                              new Type[]{Type.getType( Object.class )} ) );
+            } else {
+                mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                                    Type.getInternalName( clazz ),
+                                    "equals",
+                                    Type.getMethodDescriptor( Type.BOOLEAN_TYPE,
+                                                              new Type[]{Type.getType( Object.class )} ) );
+            }
+            mv.visitJumpInsn( Opcodes.IFEQ,
+                              c1 );
+            mv.visitLabel( c2 );
+            //     return true;
+            mv.visitInsn( Opcodes.ICONST_1 );
+            mv.visitInsn( Opcodes.IRETURN );
+            // }
+            mv.visitLabel( c1 );
+            
+
+            // return false;
+            mv.visitInsn( Opcodes.ICONST_0 );
+            mv.visitInsn( Opcodes.IRETURN );
+            final Label lastLabel = new Label();
+            mv.visitLabel( lastLabel );
+
+            mv.visitLocalVariable( "this",
+                                   "L" + className + ";",
+                                   null,
+                                   l0,
+                                   lastLabel,
+                                   0 );
+            mv.visitLocalVariable( "object",
+                                   Type.getDescriptor( Object.class ),
+                                   null,
+                                   l0,
+                                   lastLabel,
+                                   1 );
+
+            mv.visitMaxs( 0,
+                          0 );
+            mv.visitEnd();
+        }
+    }
+
+    protected static void buildCollectionEquals(final ClassWriter cw,
+                                                final String className,
+                                                final Class clazz) {
+
+        final MethodVisitor mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+                                                 "equals",
+                                                 Type.getMethodDescriptor( Type.BOOLEAN_TYPE,
+                                                                           new Type[]{Type.getType( Object.class )} ),
+                                                 null,
+                                                 null );
+        // if ( this == object ) {
+        Label l0 = new Label();
+        mv.visitLabel( l0 );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         0 );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         1 );
+        Label l1 = new Label();
+        mv.visitJumpInsn( Opcodes.IF_ACMPNE,
+                          l1 );
+        //    return true;
+        Label l2 = new Label();
+        mv.visitLabel( l2 );
+        mv.visitInsn( Opcodes.ICONST_1 );
+        mv.visitInsn( Opcodes.IRETURN );
+        // }
+        mv.visitLabel( l1 );
+        // return this.delegate.equals( object );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         0 );
+        mv.visitFieldInsn( Opcodes.GETFIELD,
+                           className,
+                           DELEGATE_FIELD_NAME,
+                           Type.getDescriptor( clazz ) );
+        mv.visitVarInsn( Opcodes.ALOAD,
+                         1 );
+        if ( clazz.isInterface() ) {
+            mv.visitMethodInsn( Opcodes.INVOKEINTERFACE,
+                                Type.getInternalName( clazz ),
+                                "equals",
+                                Type.getMethodDescriptor( Type.BOOLEAN_TYPE,
+                                                          new Type[]{Type.getType( Object.class )} ) );
+        } else {
+            mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                                Type.getInternalName( clazz ),
+                                "equals",
+                                Type.getMethodDescriptor( Type.BOOLEAN_TYPE,
+                                                          new Type[]{Type.getType( Object.class )} ) );
+        }
+        mv.visitInsn( Opcodes.IRETURN );
+        Label l3 = new Label();
+        mv.visitLabel( l3 );
+        mv.visitLocalVariable( "this",
+                               "L" + className + ";",
+                               null,
+                               l0,
+                               l3,
+                               0 );
+        mv.visitLocalVariable( "object",
+                               Type.getDescriptor( Object.class ),
+                               null,
+                               l0,
+                               l3,
+                               1 );
+        mv.visitMaxs( 0,
+                      0 );
+        mv.visitEnd();
+    }
+
+    /**
+     *  Sample of generated code for all primitive + object types
+     *  
+     *  public int hashCode() {
+     *       if( ___hashCache == 0 ) {
+     *           __hashCache = this.delegate.hashCode();
+     *       }
+     *       return this.__hashCache;
+     *   }
+     * 
+     * @param cw
+     * @param className
+     * @param clazz
+     * @param fieldTypes
+     */
+    protected static void buildHashCode(final ClassWriter cw,
+                                        final String className,
+                                        final Class clazz,
+                                        final Map fieldTypes) {
+        MethodVisitor mv;
+        // Building hashcode method
+        {
+            mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+                                 "hashCode",
+                                 Type.getMethodDescriptor( Type.INT_TYPE,
+                                                           new Type[]{} ),
+                                 null,
+                                 null );
+            mv.visitCode();
+
+            // if( this.__hashCache == 0 ) {
+            Label l0 = new Label();
+            mv.visitLabel( l0 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             0 );
+            mv.visitFieldInsn( Opcodes.GETFIELD,
+                               className,
+                               HASHCACHE_FIELD_NAME,
+                               Type.INT_TYPE.getDescriptor() );
+            Label l1 = new Label();
+            mv.visitJumpInsn( Opcodes.IFNE,
+                              l1 );
+            Label l2 = new Label();
+
+            //    this.__hashCache = this.delegate.hashCode();
+            mv.visitLabel( l2 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             0 );
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             0 );
+            mv.visitFieldInsn( Opcodes.GETFIELD,
+                               className,
+                               DELEGATE_FIELD_NAME,
+                               Type.getDescriptor( clazz ) );
+            if ( clazz.isInterface() ) {
+                mv.visitMethodInsn( Opcodes.INVOKEINTERFACE,
+                                    Type.getInternalName( clazz ),
+                                    "hashCode",
+                                    Type.getMethodDescriptor( Type.INT_TYPE,
+                                                              new Type[0] ) );
+            } else {
+                mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+                                    Type.getInternalName( clazz ),
+                                    "hashCode",
+                                    Type.getMethodDescriptor( Type.INT_TYPE,
+                                                              new Type[0] ) );
+            }
+            mv.visitFieldInsn( Opcodes.PUTFIELD,
+                               className,
+                               HASHCACHE_FIELD_NAME,
+                               Type.INT_TYPE.getDescriptor() );
+            // }
+            mv.visitLabel( l1 );
+
+            // return this.__hashCache;
+            mv.visitVarInsn( Opcodes.ALOAD,
+                             0 );
+            mv.visitFieldInsn( Opcodes.GETFIELD,
+                               className,
+                               HASHCACHE_FIELD_NAME,
+                               Type.INT_TYPE.getDescriptor() );
+            mv.visitInsn( Opcodes.IRETURN );
+            Label l3 = new Label();
+            mv.visitLabel( l3 );
+            mv.visitLocalVariable( "this",
+                                   "L" + className + ";",
+                                   null,
+                                   l0,
+                                   l3,
+                                   0 );
+
+            mv.visitMaxs( 0,
+                          0 );
+            mv.visitEnd();
+        }
+    }
+
+    /**
+     * @param exceptionTypes
+     * @return
+     */
+    private static String[] getExceptionArrayAsString(final Class[] exceptionTypes) {
+        final String[] exceptions = new String[exceptionTypes.length];
+        for ( int i = 0; i < exceptions.length; i++ ) {
+            exceptions[i] = Type.getInternalName( exceptionTypes[i] );
+        }
+        return exceptions;
+    }
+
+    /**
+     * Simple classloader
+     * @author Michael Neale
+     */
+    static class ByteArrayClassLoader extends ClassLoader {
+        public ByteArrayClassLoader(final ClassLoader parent) {
+            super( parent );
+        }
+
+        public Class defineClass(final String name,
+                                 final byte[] bytes,
+                                 final ProtectionDomain PROTECTION_DOMAIN) {
+            return defineClass( name,
+                                bytes,
+                                0,
+                                bytes.length,
+                                PROTECTION_DOMAIN );
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ShadowProxyHelper.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ShadowProxyHelper.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ShadowProxyHelper.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2006 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.base;
+
+import java.lang.reflect.Field;
+
+import org.drools.RuntimeDroolsException;
+
+/**
+ * A helper class with utility methods
+ * 
+ * @author etirelli
+ */
+public class ShadowProxyHelper {
+
+    public static void copyState(final ShadowProxy from,
+                                 final ShadowProxy to) {
+        final Field[] fields = from.getClass().getDeclaredFields();
+        for ( int i = 0; i < fields.length; i++ ) {
+            if ( fields[i].getName().endsWith( ShadowProxyFactory.FIELD_SET_FLAG ) ) {
+                fields[i].setAccessible( true );
+                try {
+                    if ( fields[i].getBoolean( from ) ) {
+                        final String fieldName = fields[i].getName().substring( 0,
+                                                                          fields[i].getName().length() - ShadowProxyFactory.FIELD_SET_FLAG.length() );
+                        final Field flag = to.getClass().getDeclaredField( fields[i].getName() );
+                        final Field fieldFrom = from.getClass().getDeclaredField( fieldName );
+                        final Field fieldTo = to.getClass().getDeclaredField( fieldName );
+                        flag.setAccessible( true );
+                        fieldFrom.setAccessible( true );
+                        fieldTo.setAccessible( true );
+
+                        // we know it is set
+                        flag.setBoolean( to,
+                                         true );
+                        // copy the value from "from" shadow proxy
+                        fieldTo.set( to,
+                                     fieldFrom.get( from ) );
+                    }
+                } catch ( final Exception e ) {
+                    throw new RuntimeDroolsException( "Unable to copy state from one shadow proxy to another" );
+                }
+
+            }
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/SimpleValueType.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/SimpleValueType.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/SimpleValueType.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,16 @@
+package org.drools.base;
+
+public class SimpleValueType {
+    public static final int UNKNOWN  = 0;
+    public static final int NULL     = 1;
+    public static final int BOOLEAN  = 2;
+    public static final int NUMBER   = 3;
+    public static final int INTEGER  = 4;
+    public static final int DECIMAL  = 5;
+    public static final int CHAR     = 6;
+    public static final int STRING   = 7;
+    public static final int DATE     = 8;
+    public static final int LIST     = 9;
+    public static final int OBJECT   = 10;
+    public static final int FUNCTION = 11; //This one is for LISP
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/TypeResolver.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/TypeResolver.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/TypeResolver.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,19 @@
+package org.drools.base;
+
+import java.util.Set;
+
+public interface TypeResolver {
+    public Set getImports();
+
+    public void addImport(String importEntry);
+
+    public Class resolveType(String className) throws ClassNotFoundException;
+
+    /**
+     * This will return the fully qualified type name (including the namespace).
+     * Eg, if it was a pojo org.drools.Cheese, then if you passed in "Cheese" you should get back
+     * "org.drools.Cheese"
+     */
+	public String getFullTypeName(String shortName) throws ClassNotFoundException;
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ValueType.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ValueType.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/ValueType.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,213 @@
+package org.drools.base;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Date;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.facttemplates.FactTemplate;
+
+public class ValueType
+    implements
+    Serializable {
+
+    private static final long      serialVersionUID  = 400L;
+
+    public static final ValueType  NULL_TYPE         = new ValueType( "null",
+                                                                      null,
+                                                                      SimpleValueType.NULL);
+    // wrapper types
+    public static final ValueType  CHAR_TYPE         = new ValueType( "Character",
+                                                                      Character.class,
+                                                                      SimpleValueType.CHAR );
+    public static final ValueType  BYTE_TYPE         = new ValueType( "Byte",
+                                                                      Byte.class,
+                                                                      SimpleValueType.INTEGER);
+    public static final ValueType  SHORT_TYPE        = new ValueType( "Short",
+                                                                      Short.class,
+                                                                      SimpleValueType.INTEGER );
+    public static final ValueType  INTEGER_TYPE      = new ValueType( "Integer",
+                                                                      Integer.class,
+                                                                      SimpleValueType.INTEGER );
+    public static final ValueType  LONG_TYPE         = new ValueType( "Long",
+                                                                      Long.class,
+                                                                      SimpleValueType.INTEGER );
+    public static final ValueType  FLOAT_TYPE        = new ValueType( "Float",
+                                                                      Float.class,
+                                                                      SimpleValueType.DECIMAL );
+    public static final ValueType  DOUBLE_TYPE       = new ValueType( "Double",
+                                                                      Double.class,
+                                                                      SimpleValueType.DECIMAL );
+    public static final ValueType  BOOLEAN_TYPE      = new ValueType( "Boolean",
+                                                                      Boolean.class,
+                                                                      SimpleValueType.BOOLEAN );
+    // primitive types
+    public static final ValueType  PCHAR_TYPE        = new ValueType( "char",
+                                                                      Character.TYPE,
+                                                                      SimpleValueType.CHAR );
+    public static final ValueType  PBYTE_TYPE        = new ValueType( "byte",
+                                                                      Byte.TYPE,
+                                                                      SimpleValueType.INTEGER );
+    public static final ValueType  PSHORT_TYPE       = new ValueType( "short",
+                                                                      Short.TYPE,
+                                                                      SimpleValueType.INTEGER );
+    public static final ValueType  PINTEGER_TYPE     = new ValueType( "int",
+                                                                      Integer.TYPE,
+                                                                      SimpleValueType.INTEGER );
+    public static final ValueType  PLONG_TYPE        = new ValueType( "long",
+                                                                      Long.TYPE,
+                                                                      SimpleValueType.INTEGER );
+    public static final ValueType  PFLOAT_TYPE       = new ValueType( "float",
+                                                                      Float.TYPE,
+                                                                      SimpleValueType.DECIMAL );
+    public static final ValueType  PDOUBLE_TYPE      = new ValueType( "double",
+                                                                      Double.TYPE,
+                                                                      SimpleValueType.DECIMAL );
+    public static final ValueType  PBOOLEAN_TYPE     = new ValueType( "boolean",
+                                                                      Boolean.TYPE,
+                                                                      SimpleValueType.BOOLEAN );
+    // other types
+    public static final ValueType  DATE_TYPE         = new ValueType( "Date",
+                                                                      Date.class,
+                                                                      SimpleValueType.DATE );
+    public static final ValueType  ARRAY_TYPE        = new ValueType( "Array",
+                                                                      Object[].class,
+                                                                      SimpleValueType.LIST );
+    public static final ValueType  STRING_TYPE       = new ValueType( "String",
+                                                                      String.class,
+                                                                      SimpleValueType.STRING );
+    public static final ValueType  OBJECT_TYPE       = new ValueType( "Object",
+                                                                      Object.class,
+                                                                      SimpleValueType.OBJECT );
+    public static final ValueType  FACTTEMPLATE_TYPE = new ValueType( "FactTemplate",
+                                                                      FactTemplate.class,
+                                                                      SimpleValueType.UNKNOWN );
+    public static final ValueType  BIG_DECIMAL_TYPE  = new ValueType( "BigDecimal",
+                                                                      BigDecimal.class,
+                                                                      SimpleValueType.OBJECT );
+    public static final ValueType  BIG_INTEGER_TYPE  = new ValueType( "BigInteger",
+                                                                      BigInteger.class,
+                                                                      SimpleValueType.OBJECT );
+
+    private final String           name;
+    private final Class            classType;
+    private final int              simpleType;
+
+    private ValueType(final String name,
+                      final Class classType,
+                      final int simpleType) {
+        this.name = name;
+        this.classType = classType;
+        this.simpleType = simpleType;
+    }
+
+    private Object readResolve() throws java.io.ObjectStreamException {
+        return determineValueType( this.classType );
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public Class getClassType() {
+        return this.classType;
+    }
+
+    public int getSimpleType() {
+        return this.simpleType;
+    }
+
+    public static ValueType determineValueType(final Class clazz) {
+        if ( clazz == null ) {
+            return ValueType.NULL_TYPE;
+        }
+        if ( clazz == FactTemplate.class ) {
+            return ValueType.FACTTEMPLATE_TYPE;
+        } else if ( clazz == Character.TYPE ) {
+            return ValueType.PCHAR_TYPE;
+        } else if ( clazz == Byte.TYPE ) {
+            return ValueType.PBYTE_TYPE;
+        } else if ( clazz == Short.TYPE ) {
+            return ValueType.PSHORT_TYPE;
+        } else if ( clazz == Integer.TYPE ) {
+            return ValueType.PINTEGER_TYPE;
+        } else if ( clazz == Long.TYPE ) {
+            return ValueType.PLONG_TYPE;
+        } else if ( clazz == Float.TYPE ) {
+            return ValueType.PFLOAT_TYPE;
+        } else if ( clazz == Double.TYPE ) {
+            return ValueType.PDOUBLE_TYPE;
+        } else if ( clazz == Boolean.TYPE ) {
+            return ValueType.PBOOLEAN_TYPE;
+        } else if ( clazz == Character.class ) {
+            return ValueType.CHAR_TYPE;
+        } else if ( clazz == Byte.class ) {
+            return ValueType.BYTE_TYPE;
+        } else if ( clazz == Short.class ) {
+            return ValueType.SHORT_TYPE;
+        } else if ( clazz == Integer.class ) {
+            return ValueType.INTEGER_TYPE;
+        } else if ( clazz == Long.class ) {
+            return ValueType.LONG_TYPE;
+        } else if ( clazz == Float.class ) {
+            return ValueType.FLOAT_TYPE;
+        } else if ( clazz == Double.class ) {
+            return ValueType.DOUBLE_TYPE;
+        } else if ( clazz == Boolean.class ) {
+            return ValueType.BOOLEAN_TYPE;
+        } else if ( clazz == java.sql.Date.class ) {
+            return ValueType.DATE_TYPE;
+        } else if ( clazz == java.util.Date.class ) {
+            return ValueType.DATE_TYPE;
+        } else if ( clazz.isArray() ) {
+            return ValueType.ARRAY_TYPE;
+        } else if ( clazz == BigDecimal.class ) {
+            return ValueType.BIG_DECIMAL_TYPE;
+        } else if ( clazz == BigInteger.class ) {
+            return ValueType.BIG_INTEGER_TYPE;
+        } else if ( clazz == String.class ) {
+            return ValueType.STRING_TYPE;
+        } else if ( clazz instanceof Object ) {
+            return ValueType.OBJECT_TYPE;
+        }
+        throw new RuntimeDroolsException( "unable to determine ValueType for Class [" + clazz + "]" );
+    }
+
+    public String toString() {
+        return "ValueType = '" + this.name + "'";
+    }
+
+    public int hashCode() {
+        return this.name.hashCode();
+    }
+
+    public boolean equals(final Object object) {
+        if ( object == this ) {
+            return true;
+        }
+
+        return false;
+    }
+
+    public boolean isBoolean() {
+        return ((this.classType == Boolean.class) || (this.classType == Boolean.TYPE));
+    }
+
+    public boolean isNumber() {
+        return (this.simpleType == SimpleValueType.INTEGER || this.simpleType == SimpleValueType.DECIMAL || this.simpleType == SimpleValueType.CHAR);
+    }
+
+    public boolean isIntegerNumber() {
+        return this.simpleType == SimpleValueType.INTEGER;
+    }
+
+    public boolean isFloatNumber() {
+        return this.simpleType == SimpleValueType.DECIMAL;
+    }
+
+    public boolean isChar() {
+        return this.simpleType == SimpleValueType.CHAR;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/AccumulateFunction.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/AccumulateFunction.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/AccumulateFunction.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Jun 20, 2007
+ */
+package org.drools.base.accumulators;
+
+import java.io.Serializable;
+
+/**
+ * An interface for accumulate external function implementations
+ * 
+ * @author etirelli
+ *
+ */
+public interface AccumulateFunction extends Serializable {
+
+    /**
+     * Creates and returns a new context object
+     * @return
+     */
+    public Object createContext();
+
+    /**
+     * Initializes the accumulator
+     * @param context
+     * @throws Exception
+     */
+    public void init(Object context) throws Exception;
+
+    /**
+     * Executes the accumulation action
+     * @param context
+     * @param value
+     */
+    public void accumulate(Object context,
+                           Object value);
+
+    /**
+     * Reverses the accumulation action
+     * @param context
+     * @param value
+     * @throws Exception
+     */
+    public void reverse(Object context,
+                        Object value) throws Exception;
+
+    /**
+     * Returns the current value in this accumulation session
+     * 
+     * @param context
+     * @return
+     * @throws Exception
+     */
+    public Object getResult(Object context) throws Exception;
+
+    /**
+     * True if the function supports reverse. False otherwise.
+     * 
+     * @return
+     */
+    public boolean supportsReverse();
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/AverageAccumulateFunction.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/AverageAccumulateFunction.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/AverageAccumulateFunction.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Jun 21, 2007
+ */
+package org.drools.base.accumulators;
+
+
+/**
+ * An implementation of an accumulator capable of calculating average values
+ * 
+ * @author etirelli
+ *
+ */
+public class AverageAccumulateFunction implements AccumulateFunction {
+
+    protected static class AverageData {
+        public int    count = 0;
+        public double total = 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#createContext()
+     */
+    public Object createContext() {
+        return new AverageData();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#init(java.lang.Object)
+     */
+    public void init(Object context) throws Exception {
+        AverageData data = (AverageData) context;
+        data.count = 0;
+        data.total = 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#accumulate(java.lang.Object, java.lang.Object)
+     */
+    public void accumulate(Object context,
+                           Object value) {
+        AverageData data = (AverageData) context;
+        data.count++;
+        data.total += ((Number) value).doubleValue();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#reverse(java.lang.Object, java.lang.Object)
+     */
+    public void reverse(Object context,
+                        Object value) throws Exception {
+        AverageData data = (AverageData) context;
+        data.count--;
+        data.total -= ((Number) value).doubleValue();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#getResult(java.lang.Object)
+     */
+    public Object getResult(Object context) throws Exception {
+        AverageData data = (AverageData) context;
+        return new Double( data.count == 0 ? 0 : data.total / data.count );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#supportsReverse()
+     */
+    public boolean supportsReverse() {
+        return true;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/CountAccumulateFunction.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/CountAccumulateFunction.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/CountAccumulateFunction.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Jun 21, 2007
+ */
+package org.drools.base.accumulators;
+
+
+/**
+ * An implementation of an accumulator capable of counting occurences
+ * 
+ * @author etirelli
+ *
+ */
+public class CountAccumulateFunction implements AccumulateFunction {
+
+    protected static class CountData {
+        public long   count = 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#createContext()
+     */
+    public Object createContext() {
+        return new CountData();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#init(java.lang.Object)
+     */
+    public void init(Object context) throws Exception {
+        CountData data = (CountData) context;
+        data.count = 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#accumulate(java.lang.Object, java.lang.Object)
+     */
+    public void accumulate(Object context,
+                           Object value) {
+        CountData data = (CountData) context;
+        data.count++;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#reverse(java.lang.Object, java.lang.Object)
+     */
+    public void reverse(Object context,
+                        Object value) throws Exception {
+        CountData data = (CountData) context;
+        data.count--;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#getResult(java.lang.Object)
+     */
+    public Object getResult(Object context) throws Exception {
+        CountData data = (CountData) context;
+        return new Long( data.count );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#supportsReverse()
+     */
+    public boolean supportsReverse() {
+        return true;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/JavaAccumulatorFunctionExecutor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/JavaAccumulatorFunctionExecutor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/JavaAccumulatorFunctionExecutor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Jun 20, 2007
+ */
+package org.drools.base.accumulators;
+
+import org.drools.WorkingMemory;
+import org.drools.common.InternalFactHandle;
+import org.drools.rule.Declaration;
+import org.drools.spi.Accumulator;
+import org.drools.spi.ReturnValueExpression;
+import org.drools.spi.Tuple;
+
+/**
+ * An MVEL accumulator function executor implementation
+ * 
+ * @author etirelli
+ */
+public class JavaAccumulatorFunctionExecutor
+    implements
+    Accumulator {
+
+    private static final long           serialVersionUID = 400L;
+
+    private ReturnValueExpression expression;
+    private final AccumulateFunction   function;
+
+    public JavaAccumulatorFunctionExecutor(final AccumulateFunction function) {
+        super();
+        this.function = function;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.spi.Accumulator#createContext()
+     */
+    public Object createContext() {
+        return this.function.createContext();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.spi.Accumulator#init(java.lang.Object, org.drools.spi.Tuple, org.drools.rule.Declaration[], org.drools.WorkingMemory)
+     */
+    public void init(Object workingMemoryContext,
+                     Object context,
+                     Tuple leftTuple,
+                     Declaration[] declarations,
+                     WorkingMemory workingMemory) throws Exception {
+        this.function.init( context );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.spi.Accumulator#accumulate(java.lang.Object, org.drools.spi.Tuple, org.drools.common.InternalFactHandle, org.drools.rule.Declaration[], org.drools.rule.Declaration[], org.drools.WorkingMemory)
+     */
+    public void accumulate(Object workingMemoryContext,
+                           Object context,
+                           Tuple leftTuple,
+                           InternalFactHandle handle,
+                           Declaration[] declarations,
+                           Declaration[] innerDeclarations,
+                           WorkingMemory workingMemory) throws Exception {
+        final Object value = this.expression.evaluate( handle.getObject(),
+                                                       leftTuple,
+                                                       declarations,
+                                                       innerDeclarations,
+                                                       workingMemory ).getValue();
+        this.function.accumulate( context,
+                                  value );
+    }
+
+    public void reverse(Object workingMemoryContext,
+                        Object context,
+                        Tuple leftTuple,
+                        InternalFactHandle handle,
+                        Declaration[] declarations,
+                        Declaration[] innerDeclarations,
+                        WorkingMemory workingMemory) throws Exception {
+        final Object value = this.expression.evaluate( handle.getObject(),
+                                                       leftTuple,
+                                                       declarations,
+                                                       innerDeclarations,
+                                                       workingMemory ).getValue();
+        this.function.reverse( context,
+                               value );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.spi.Accumulator#getResult(java.lang.Object, org.drools.spi.Tuple, org.drools.rule.Declaration[], org.drools.WorkingMemory)
+     */
+    public Object getResult(Object workingMemoryContext,
+                            Object context,
+                            Tuple leftTuple,
+                            Declaration[] declarations,
+                            WorkingMemory workingMemory) throws Exception {
+        return this.function.getResult( context );
+    }
+
+    public boolean supportsReverse() {
+        return this.function.supportsReverse();
+    }
+
+    public ReturnValueExpression getExpression() {
+        return expression;
+    }
+
+    public void setExpression(ReturnValueExpression expression) {
+        this.expression = expression;
+    }
+
+    public Object createWorkingMemoryContext() {
+        // no working memory context needed 
+        return null;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/MVELAccumulatorFunctionExecutor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/MVELAccumulatorFunctionExecutor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/MVELAccumulatorFunctionExecutor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Jun 20, 2007
+ */
+package org.drools.base.accumulators;
+
+import java.io.Serializable;
+import java.util.Map;
+
+import org.drools.WorkingMemory;
+import org.drools.base.mvel.DroolsMVELFactory;
+import org.drools.common.InternalFactHandle;
+import org.drools.rule.Declaration;
+import org.drools.spi.Accumulator;
+import org.drools.spi.Tuple;
+import org.mvel.MVEL;
+
+/**
+ * An MVEL accumulator function executor implementation
+ * 
+ * @author etirelli
+ */
+public class MVELAccumulatorFunctionExecutor
+    implements
+    Accumulator {
+
+    private static final long        serialVersionUID = 400L;
+
+    private final Object             dummy            = new Object();
+    private final DroolsMVELFactory  model;
+    private final Serializable       expression;
+    private final AccumulateFunction function;
+
+    public MVELAccumulatorFunctionExecutor(final DroolsMVELFactory factory,
+                                           final Serializable expression,
+                                           final AccumulateFunction function) {
+        super();
+        this.model = factory;
+        this.expression = expression;
+        this.function = function;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.spi.Accumulator#createContext()
+     */
+    public Object createContext() {
+        return this.function.createContext();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.spi.Accumulator#init(java.lang.Object, org.drools.spi.Tuple, org.drools.rule.Declaration[], org.drools.WorkingMemory)
+     */
+    public void init(Object workingMemoryContext,
+                     Object context,
+                     Tuple leftTuple,
+                     Declaration[] declarations,
+                     WorkingMemory workingMemory) throws Exception {
+        this.function.init( context );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.spi.Accumulator#accumulate(java.lang.Object, org.drools.spi.Tuple, org.drools.common.InternalFactHandle, org.drools.rule.Declaration[], org.drools.rule.Declaration[], org.drools.WorkingMemory)
+     */
+    public void accumulate(Object workingMemoryContext,
+                           Object context,
+                           Tuple leftTuple,
+                           InternalFactHandle handle,
+                           Declaration[] declarations,
+                           Declaration[] innerDeclarations,
+                           WorkingMemory workingMemory) throws Exception {
+        DroolsMVELFactory factory = (DroolsMVELFactory) workingMemoryContext;
+        factory.setContext( leftTuple,
+                            null,
+                            handle.getObject(),
+                            workingMemory,
+                            null );
+        final Object value = MVEL.executeExpression( this.expression,
+                                                     this.dummy,
+                                                     factory );
+        this.function.accumulate( context,
+                                  value );
+    }
+
+    public void reverse(Object workingMemoryContext,
+                        Object context,
+                        Tuple leftTuple,
+                        InternalFactHandle handle,
+                        Declaration[] declarations,
+                        Declaration[] innerDeclarations,
+                        WorkingMemory workingMemory) throws Exception {
+        DroolsMVELFactory factory = (DroolsMVELFactory) workingMemoryContext;
+        factory.setContext( leftTuple,
+                               null,
+                               handle.getObject(),
+                               workingMemory,
+                               null );
+        final Object value = MVEL.executeExpression( this.expression,
+                                                     this.dummy,
+                                                     factory );
+        this.function.reverse( context,
+                               value );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.spi.Accumulator#getResult(java.lang.Object, org.drools.spi.Tuple, org.drools.rule.Declaration[], org.drools.WorkingMemory)
+     */
+    public Object getResult(Object workingMemoryContext,
+                            Object context,
+                            Tuple leftTuple,
+                            Declaration[] declarations,
+                            WorkingMemory workingMemory) throws Exception {
+        return this.function.getResult( context );
+    }
+
+    public boolean supportsReverse() {
+        return this.function.supportsReverse();
+    }
+
+    public Object createWorkingMemoryContext() {
+        return this.model.clone();
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/MaxAccumulateFunction.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/MaxAccumulateFunction.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/MaxAccumulateFunction.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Jun 21, 2007
+ */
+package org.drools.base.accumulators;
+
+
+/**
+ * An implementation of an accumulator capable of calculating maximum values
+ * 
+ * @author etirelli
+ *
+ */
+public class MaxAccumulateFunction implements AccumulateFunction {
+
+    protected static class MaxData {
+        public double max = Double.MIN_VALUE;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#createContext()
+     */
+    public Object createContext() {
+        return new MaxData();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#init(java.lang.Object)
+     */
+    public void init(Object context) throws Exception {
+        MaxData data = (MaxData) context;
+        data.max = Double.MIN_VALUE;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#accumulate(java.lang.Object, java.lang.Object)
+     */
+    public void accumulate(Object context,
+                           Object value) {
+        MaxData data = (MaxData) context;
+        data.max = Math.max( data.max, ((Number)value).doubleValue() );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#reverse(java.lang.Object, java.lang.Object)
+     */
+    public void reverse(Object context,
+                        Object value) throws Exception {
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#getResult(java.lang.Object)
+     */
+    public Object getResult(Object context) throws Exception {
+        MaxData data = (MaxData) context;
+        return new Double( data.max );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#supportsReverse()
+     */
+    public boolean supportsReverse() {
+        return false;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/MinAccumulateFunction.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/MinAccumulateFunction.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/MinAccumulateFunction.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Jun 21, 2007
+ */
+package org.drools.base.accumulators;
+
+
+/**
+ * An implementation of an accumulator capable of calculating minimun values
+ * 
+ * @author etirelli
+ *
+ */
+public class MinAccumulateFunction implements AccumulateFunction {
+
+    protected static class MaxData {
+        public double min = Double.MAX_VALUE;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#createContext()
+     */
+    public Object createContext() {
+        return new MaxData();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#init(java.lang.Object)
+     */
+    public void init(Object context) throws Exception {
+        MaxData data = (MaxData) context;
+        data.min = Double.MAX_VALUE;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#accumulate(java.lang.Object, java.lang.Object)
+     */
+    public void accumulate(Object context,
+                           Object value) {
+        MaxData data = (MaxData) context;
+        data.min = Math.min( data.min, ((Number)value).doubleValue() );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#reverse(java.lang.Object, java.lang.Object)
+     */
+    public void reverse(Object context,
+                        Object value) throws Exception {
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#getResult(java.lang.Object)
+     */
+    public Object getResult(Object context) throws Exception {
+        MaxData data = (MaxData) context;
+        return new Double( data.min );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#supportsReverse()
+     */
+    public boolean supportsReverse() {
+        return false;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/SumAccumulateFunction.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/SumAccumulateFunction.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/accumulators/SumAccumulateFunction.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Jun 21, 2007
+ */
+package org.drools.base.accumulators;
+
+
+/**
+ * An implementation of an accumulator capable of calculating sum of values
+ * 
+ * @author etirelli
+ *
+ */
+public class SumAccumulateFunction implements AccumulateFunction {
+
+    protected static class SumData {
+        public double total = 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#createContext()
+     */
+    public Object createContext() {
+        return new SumData();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#init(java.lang.Object)
+     */
+    public void init(Object context) throws Exception {
+        SumData data = (SumData) context;
+        data.total = 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#accumulate(java.lang.Object, java.lang.Object)
+     */
+    public void accumulate(Object context,
+                           Object value) {
+        SumData data = (SumData) context;
+        data.total += ((Number) value).doubleValue();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#reverse(java.lang.Object, java.lang.Object)
+     */
+    public void reverse(Object context,
+                        Object value) throws Exception {
+        SumData data = (SumData) context;
+        data.total -= ((Number) value).doubleValue();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#getResult(java.lang.Object)
+     */
+    public Object getResult(Object context) throws Exception {
+        SumData data = (SumData) context;
+        return new Double( data.total );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.accumulators.AccumulateFunction#supportsReverse()
+     */
+    public boolean supportsReverse() {
+        return true;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/dataproviders/MVELDataProvider.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/dataproviders/MVELDataProvider.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/dataproviders/MVELDataProvider.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,55 @@
+package org.drools.base.dataproviders;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+
+import org.drools.WorkingMemory;
+import org.drools.base.mvel.DroolsMVELFactory;
+import org.drools.rule.Declaration;
+import org.drools.spi.DataProvider;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
+import org.mvel.MVEL;
+
+public class MVELDataProvider
+    implements
+    DataProvider,
+    Serializable  {
+
+    private final Serializable      expression;
+    private final DroolsMVELFactory factory;
+
+    public MVELDataProvider(final Serializable expression,
+                            final DroolsMVELFactory factory) {
+        this.expression = expression;
+        this.factory = factory;
+    }
+
+    public Declaration[] getRequiredDeclarations() {
+        return new Declaration[]{};
+        //return factory.getRequiredDeclarations();
+    }
+
+    public Iterator getResults(final Tuple tuple,
+                               final WorkingMemory wm,
+                               final PropagationContext ctx) {
+        this.factory.setContext( tuple,
+                                 null,
+                                 null,
+                                 wm,
+                                 null );
+
+        //this.expression.
+        final Object result = MVEL.executeExpression( this.expression,
+                                                      this.factory );
+        if ( result instanceof Collection ) {
+            return ((Collection) result).iterator();
+        } else if ( result instanceof Iterator ) {
+            return (Iterator) result;
+        } else {
+            return Collections.singletonList( result ).iterator();
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/AfterEvaluatorDefinition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/AfterEvaluatorDefinition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/AfterEvaluatorDefinition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 6, 2007
+ */
+package org.drools.base.evaluators;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.BaseEvaluator;
+import org.drools.base.ValueType;
+import org.drools.common.EventFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.VariableRestriction.ObjectVariableContextEntry;
+import org.drools.rule.VariableRestriction.VariableContextEntry;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldValue;
+
+/**
+ * The implementation of the 'after' evaluator definition
+ * 
+ * @author etirelli
+ */
+public class AfterEvaluatorDefinition
+    implements
+    EvaluatorDefinition {
+
+    public static final Operator   AFTER         = Operator.addOperatorToRegistry( "after",
+                                                                                   false );
+    public static final Operator   NOT_AFTER     = Operator.addOperatorToRegistry( "after",
+                                                                                   true );
+
+    private static final String[]  SUPPORTED_IDS = {AFTER.getOperatorString()};
+
+    private Map<String, Evaluator> cache         = Collections.emptyMap();
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  null );
+    }
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator,
+                                  String parameterText) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  parameterText );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public Evaluator getEvaluator(final ValueType type,
+                                  final String operatorId,
+                                  final boolean isNegated,
+                                  final String parameterText) {
+        if ( this.cache == Collections.EMPTY_MAP ) {
+            this.cache = new HashMap<String, Evaluator>();
+        }
+        String key = isNegated + ":" + parameterText;
+        Evaluator eval = this.cache.get( key );
+        if ( eval == null ) {
+            eval = new AfterEvaluator( type,
+                                       isNegated,
+                                       parameterText );
+            this.cache.put( key,
+                            eval );
+        }
+        return eval;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public String[] getEvaluatorIds() {
+        return SUPPORTED_IDS;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean isNegatable() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean operatesOnFactHandles() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean supportsType(ValueType type) {
+        // supports all types, since it operates over fact handles
+        // Note: should we change this interface to allow checking of event classes only?
+        return true;
+    }
+
+    /**
+     * Implements the 'after' evaluator itself
+     */
+    public static class AfterEvaluator extends BaseEvaluator {
+        private static final long serialVersionUID = -4833205637340977934L;
+
+        private long              initRange;
+        private long              finalRange;
+
+        public AfterEvaluator(final ValueType type,
+                              final boolean isNegated,
+                              final String parameters) {
+            super( type,
+                   isNegated ? NOT_AFTER : AFTER );
+            this.parseParameters( parameters );
+        }
+
+        @Override
+        public Object prepareObject(InternalFactHandle handle) {
+            return handle;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            throw new RuntimeDroolsException( "The 'after' operator can only be used to compare one event to another, and never to compare to literal constraints." );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context,
+                                           final Object left) {
+            if ( context.rightNull ) {
+                return false;
+            }
+            long dist = ((EventFactHandle) ((ObjectVariableContextEntry) context).right).getStartTimestamp() - ((EventFactHandle) left).getEndTimestamp();
+            return this.getOperator().isNegated() ^ ( dist >= this.initRange && dist <= this.finalRange ); 
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context,
+                                          final Object right) {
+            if ( context.extractor.isNullValue( workingMemory,
+                                                right ) ) {
+                return false;
+            }
+            long dist = ((EventFactHandle) right).getStartTimestamp() - ((EventFactHandle) ((ObjectVariableContextEntry) context).left).getEndTimestamp();
+
+            return this.getOperator().isNegated() ^ ( dist >= this.initRange && dist <= this.finalRange );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2,
+                                final Object object2) {
+            if ( extractor1.isNullValue( workingMemory,
+                                         object1 ) ) {
+                return false;
+            }
+            long dist = ((EventFactHandle) object1).getStartTimestamp() - ((EventFactHandle) object2).getEndTimestamp();
+            return this.getOperator().isNegated() ^ ( dist >= this.initRange && dist <= this.finalRange );
+        }
+
+        public String toString() {
+            return this.getOperator().toString()+ "[" + initRange + ", " + finalRange + "]";
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int PRIME = 31;
+            int result = super.hashCode();
+            result = PRIME * result + (int) (finalRange ^ (finalRange >>> 32));
+            result = PRIME * result + (int) (initRange ^ (initRange >>> 32));
+            return result;
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#equals(java.lang.Object)
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if ( this == obj ) return true;
+            if ( !super.equals( obj ) ) return false;
+            if ( getClass() != obj.getClass() ) return false;
+            final AfterEvaluator other = (AfterEvaluator) obj;
+            return finalRange == other.finalRange && initRange == other.initRange;
+        }
+
+        /**
+         * This methods tries to parse the string of parameters to customize 
+         * the evaluator.
+         * 
+         * @param parameters
+         */
+        private void parseParameters(String parameters) {
+            if ( parameters == null || parameters.trim().length() == 0 ) {
+                // open bounded range
+                this.initRange = 1;
+                this.finalRange = Long.MAX_VALUE;
+                return;
+            }
+
+            try {
+                String[] ranges = parameters.split( "," );
+                if ( ranges.length == 1 ) {
+                    // deterministic point in time
+                    this.initRange = Long.parseLong( ranges[0] );
+                    this.finalRange = this.initRange;
+                } else if ( ranges.length == 2 ) {
+                    // regular range
+                    this.initRange = Long.parseLong( ranges[0] );
+                    this.finalRange = Long.parseLong( ranges[1] );
+                } else {
+                    throw new RuntimeDroolsException( "[After Evaluator]: Not possible to parse parameters: '" + parameters + "'" );
+                }
+            } catch ( NumberFormatException e ) {
+                throw new RuntimeDroolsException( "[After Evaluator]: Not possible to parse parameters: '" + parameters + "'",
+                                                  e );
+            }
+        }
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/BeforeEvaluatorDefinition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/BeforeEvaluatorDefinition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/BeforeEvaluatorDefinition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 6, 2007
+ */
+package org.drools.base.evaluators;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.BaseEvaluator;
+import org.drools.base.ValueType;
+import org.drools.common.EventFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.VariableRestriction.ObjectVariableContextEntry;
+import org.drools.rule.VariableRestriction.VariableContextEntry;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldValue;
+
+/**
+ * The implementation of the 'before' evaluator definition
+ * 
+ * @author mgroch
+ */
+public class BeforeEvaluatorDefinition
+    implements
+    EvaluatorDefinition {
+
+    public static final Operator  BEFORE       = Operator.addOperatorToRegistry( "before",
+                                                                                  false );
+    public static final Operator  NOT_BEFORE   = Operator.addOperatorToRegistry( "before",
+                                                                                  true );
+    
+    private static final String[] SUPPORTED_IDS = { BEFORE.getOperatorString() };
+    
+    private Map<String, BeforeEvaluator> cache        = Collections.emptyMap();
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  null );
+    }
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator,
+                                  String parameterText) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  parameterText );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public Evaluator getEvaluator(final ValueType type,
+                                  final String operatorId,
+                                  final boolean isNegated,
+                                  final String parameterText) {
+        if ( this.cache == Collections.EMPTY_MAP ) {
+            this.cache = new HashMap<String, BeforeEvaluator>();
+        }
+        String key = isNegated + ":" + parameterText;
+        BeforeEvaluator eval = this.cache.get( key );
+        if ( eval == null ) {
+            eval = new BeforeEvaluator( type,
+                                       isNegated,
+                                       parameterText );
+            this.cache.put( key,
+                            eval );
+        }
+        return eval;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public String[] getEvaluatorIds() {
+        return SUPPORTED_IDS;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean isNegatable() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean operatesOnFactHandles() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean supportsType(ValueType type) {
+        // supports all types, since it operates over fact handles
+        // Note: should we change this interface to allow checking of event classes only?
+        return true;
+    }
+
+    /**
+     * Implements the 'before' evaluator itself
+     */
+    public static class BeforeEvaluator extends BaseEvaluator {
+		private static final long serialVersionUID = -4778826341073034320L;
+		
+		private long                  initRange;
+        private long                  finalRange;
+
+        public BeforeEvaluator(final ValueType type,
+                              final boolean isNegated,
+                              final String parameters) {
+            super( type,
+                   isNegated ? NOT_BEFORE : BEFORE );
+            this.parseParameters( parameters );
+        }
+        
+        @Override
+        public Object prepareObject(InternalFactHandle handle) {
+            return handle;
+        }
+        
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            throw new RuntimeDroolsException( "The 'before' operator can only be used to compare one event to another, and never to compare to literal constraints." );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context,
+                                           final Object left) {
+            if ( context.rightNull ) {
+                return false;
+            }
+            long dist = ((EventFactHandle) left ).getStartTimestamp() - 
+            			((EventFactHandle)((ObjectVariableContextEntry) context).right).getEndTimestamp();
+            return this.getOperator().isNegated() ^ (dist >= this.initRange && dist <= this.finalRange);
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context,
+                                          final Object right) {
+            if ( context.extractor.isNullValue( workingMemory,
+                                                right ) ) {
+                return false;
+            }
+            long dist = ((EventFactHandle) ((ObjectVariableContextEntry) context).left).getStartTimestamp() - 
+            			((EventFactHandle) right ).getEndTimestamp();
+
+            return this.getOperator().isNegated() ^ (  dist >= this.initRange && dist <= this.finalRange );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2,
+                                final Object object2) {
+            if ( extractor1.isNullValue( workingMemory,
+                                         object1 ) ) {
+                return false;
+            }
+            long dist = ((EventFactHandle) object2 ).getStartTimestamp() - ((EventFactHandle) object1 ).getEndTimestamp();
+            return this.getOperator().isNegated() ^ (  dist >= this.initRange && dist <= this.finalRange ) ;
+        }
+
+        public String toString() {
+            return this.getOperator().toString() + "[" + initRange + ", " + finalRange + "]";
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int PRIME = 31;
+            int result = super.hashCode();
+            result = PRIME * result + (int) (finalRange ^ (finalRange >>> 32));
+            result = PRIME * result + (int) (initRange ^ (initRange >>> 32));
+            return result;
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#equals(java.lang.Object)
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if ( this == obj ) return true;
+            if ( !super.equals( obj ) ) return false;
+            if ( getClass() != obj.getClass() ) return false;
+            final BeforeEvaluator other = (BeforeEvaluator) obj;
+            return finalRange == other.finalRange && initRange == other.initRange;
+        }
+
+        /**
+         * This methods tries to parse the string of parameters to customize 
+         * the evaluator.
+         * 
+         * @param parameters
+         */
+        private void parseParameters(String parameters) {
+            if ( parameters == null || parameters.trim().length() == 0 ) {
+                // open bounded range
+                this.initRange = 1;
+                this.finalRange = Long.MAX_VALUE;
+                return;
+            }
+
+            try {
+                String[] ranges = parameters.split( "," );
+                if ( ranges.length == 1 ) {
+                    // deterministic point in time
+                    this.initRange = Long.parseLong( ranges[0] );
+                    this.finalRange = this.initRange;
+                } else if ( ranges.length == 2 ) {
+                    // regular range
+                    this.initRange = Long.parseLong( ranges[0] );
+                    this.finalRange = Long.parseLong( ranges[1] );
+                } else {
+                    throw new RuntimeDroolsException( "[Before Evaluator]: Not possible to parse parameters: '" + parameters + "'" );
+                }
+            } catch ( NumberFormatException e ) {
+                throw new RuntimeDroolsException( "[Before Evaluator]: Not possible to parse parameters: '" + parameters + "'",
+                                                  e );
+            }
+        }
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/CoincidesEvaluatorDefinition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/CoincidesEvaluatorDefinition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/CoincidesEvaluatorDefinition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 6, 2007
+ */
+package org.drools.base.evaluators;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.BaseEvaluator;
+import org.drools.base.ValueType;
+import org.drools.common.EventFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.VariableRestriction.ObjectVariableContextEntry;
+import org.drools.rule.VariableRestriction.VariableContextEntry;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldValue;
+
+/**
+ * The implementation of the 'coincides' evaluator definition
+ * 
+ * @author mgroch
+ */
+public class CoincidesEvaluatorDefinition
+    implements
+    EvaluatorDefinition {
+
+    public static final Operator  COINCIDES       = Operator.addOperatorToRegistry( "coincides",
+                                                                                  false );
+    public static final Operator  COINCIDES_NOT   = Operator.addOperatorToRegistry( "coincides",
+                                                                                  true );
+    
+    private static final String[] SUPPORTED_IDS = { COINCIDES.getOperatorString() };
+    
+    private Map<String, CoincidesEvaluator> cache        = Collections.emptyMap();
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  null );
+    }
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator,
+                                  String parameterText) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  parameterText );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public Evaluator getEvaluator(final ValueType type,
+                                  final String operatorId,
+                                  final boolean isNegated,
+                                  final String parameterText) {
+        if ( this.cache == Collections.EMPTY_MAP ) {
+            this.cache = new HashMap<String, CoincidesEvaluator>();
+        }
+        String key = isNegated + ":" + parameterText;
+        CoincidesEvaluator eval = this.cache.get( key );
+        if ( eval == null ) {
+            eval = new CoincidesEvaluator( type,
+                                       isNegated,
+                                       parameterText );
+            this.cache.put( key,
+                            eval );
+        }
+        return eval;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public String[] getEvaluatorIds() {
+        return SUPPORTED_IDS;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean isNegatable() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean operatesOnFactHandles() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean supportsType(ValueType type) {
+        // supports all types, since it operates over fact handles
+        // Note: should we change this interface to allow checking of event classes only?
+        return true;
+    }
+
+    /**
+     * Implements the 'coincides' evaluator itself
+     */
+    public static class CoincidesEvaluator extends BaseEvaluator {		
+		private static final long serialVersionUID = 6031520837249122183L;
+		
+		private long                  startDev;
+        private long                  endDev;
+
+        public CoincidesEvaluator(final ValueType type,
+                              final boolean isNegated,
+                              final String parameters) {
+            super( type,
+                   isNegated ? COINCIDES_NOT : COINCIDES );
+            this.parseParameters( parameters );
+        }
+        
+        @Override
+        public Object prepareObject(InternalFactHandle handle) {
+            return handle;
+        }
+        
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            throw new RuntimeDroolsException( "The 'coincides' operator can only be used to compare one event to another, and never to compare to literal constraints." );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context,
+                                           final Object left) {
+            if ( context.rightNull ) {
+                return false;
+            }
+            long distStart = Math.abs(((EventFactHandle)((ObjectVariableContextEntry) context).right).getStartTimestamp() - 
+                        	 ((EventFactHandle) left ).getStartTimestamp());
+            long distEnd = Math.abs(((EventFactHandle)((ObjectVariableContextEntry) context).right).getEndTimestamp() - 
+       	 				   ((EventFactHandle) left ).getEndTimestamp());
+            return this.getOperator().isNegated() ^ ( distStart <= this.startDev && distEnd <= this.endDev);
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context,
+                                          final Object right) {
+            if ( context.extractor.isNullValue( workingMemory,
+                                                right ) ) {
+                return false;
+            }
+            long distStart = Math.abs(((EventFactHandle) right ).getStartTimestamp() - 
+                        	 ((EventFactHandle) ((ObjectVariableContextEntry) context).left).getStartTimestamp());
+            long distEnd = Math.abs(((EventFactHandle) right ).getEndTimestamp() - 
+               	 		   ((EventFactHandle) ((ObjectVariableContextEntry) context).left).getEndTimestamp());
+            return this.getOperator().isNegated() ^ ( distStart <= this.startDev && distEnd <= this.endDev );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2,
+                                final Object object2) {
+            if ( extractor1.isNullValue( workingMemory,
+                                         object1 ) ) {
+                return false;
+            }
+            long distStart = Math.abs(((EventFactHandle) object1 ).getStartTimestamp() - ((EventFactHandle) object2 ).getStartTimestamp());
+            long distEnd = Math.abs(((EventFactHandle) object1 ).getEndTimestamp() - ((EventFactHandle) object2 ).getEndTimestamp());
+            return this.getOperator().isNegated() ^ ( distStart <= this.startDev && distEnd <= this.endDev );
+        }
+
+        public String toString() {
+            return "coincides[" + startDev + ", " + endDev + "]";
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int PRIME = 31;
+            int result = super.hashCode();
+            result = PRIME * result + (int) (endDev ^ (endDev >>> 32));
+            result = PRIME * result + (int) (startDev ^ (startDev >>> 32));
+            return result;
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#equals(java.lang.Object)
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if ( this == obj ) return true;
+            if ( !super.equals( obj ) ) return false;
+            if ( getClass() != obj.getClass() ) return false;
+            final CoincidesEvaluator other = (CoincidesEvaluator) obj;
+            return endDev == other.endDev && startDev == other.startDev;
+        }
+
+        /**
+         * This methods tries to parse the string of parameters to customize 
+         * the evaluator.
+         * 
+         * @param parameters
+         */
+        private void parseParameters(String parameters) {
+            if ( parameters == null || parameters.trim().length() == 0 ) {
+                // exact matching
+                this.startDev = 0;
+                this.endDev = 0;
+                return;
+            }
+
+            try {
+                String[] ranges = parameters.split( "," );
+                if ( ranges.length == 1 ) {
+                    // same max. deviation at start and end of interval
+                    this.startDev = Long.parseLong( ranges[0] );
+                    this.endDev = this.startDev;
+                } else if ( ranges.length == 2 ) {
+                    // different max. deviation at start and end of interval
+                    this.startDev = Long.parseLong( ranges[0] );
+                    this.endDev = Long.parseLong( ranges[1] );
+                } else {
+                    throw new RuntimeDroolsException( "[Coincides Evaluator]: Not possible to parse parameters: '" + parameters + "'" );
+                }
+            } catch ( NumberFormatException e ) {
+                throw new RuntimeDroolsException( "[Coincides Evaluator]: Not possible to parse parameters: '" + parameters + "'",
+                                                  e );
+            }
+        }
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/ComparableEvaluatorsDefinition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/ComparableEvaluatorsDefinition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/ComparableEvaluatorsDefinition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,2632 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 6, 2007
+ */
+package org.drools.base.evaluators;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Comparator;
+import java.util.Date;
+
+import org.drools.base.BaseEvaluator;
+import org.drools.base.ShadowProxy;
+import org.drools.base.ValueType;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.VariableRestriction.CharVariableContextEntry;
+import org.drools.rule.VariableRestriction.DoubleVariableContextEntry;
+import org.drools.rule.VariableRestriction.LongVariableContextEntry;
+import org.drools.rule.VariableRestriction.ObjectVariableContextEntry;
+import org.drools.rule.VariableRestriction.VariableContextEntry;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldValue;
+import org.drools.util.DateUtils;
+
+/**
+ * This class defines all the comparable built in 
+ * evaluators like >, >=, etc.
+ * 
+ * @author etirelli
+ */
+public class ComparableEvaluatorsDefinition implements EvaluatorDefinition {
+    
+    private static final String[] SUPPORTED_IDS = { Operator.LESS.getOperatorString(), Operator.LESS_OR_EQUAL.getOperatorString(),
+                                                    Operator.GREATER.getOperatorString(), Operator.GREATER_OR_EQUAL.getOperatorString() };
+    private EvaluatorCache evaluators = new EvaluatorCache() {
+        private static final long serialVersionUID = 4782368623L;
+        {
+            addEvaluator( ValueType.BIG_DECIMAL_TYPE,   Operator.LESS,                BigDecimalLessEvaluator.INSTANCE );
+            addEvaluator( ValueType.BIG_DECIMAL_TYPE,   Operator.LESS_OR_EQUAL,       BigDecimalLessOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.BIG_DECIMAL_TYPE,   Operator.GREATER,             BigDecimalGreaterEvaluator.INSTANCE );
+            addEvaluator( ValueType.BIG_DECIMAL_TYPE,   Operator.GREATER_OR_EQUAL,    BigDecimalGreaterOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.BIG_INTEGER_TYPE,   Operator.LESS,                BigIntegerLessEvaluator.INSTANCE );
+            addEvaluator( ValueType.BIG_INTEGER_TYPE,   Operator.LESS_OR_EQUAL,       BigIntegerLessOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.BIG_INTEGER_TYPE,   Operator.GREATER,             BigIntegerGreaterEvaluator.INSTANCE );
+            addEvaluator( ValueType.BIG_INTEGER_TYPE,   Operator.GREATER_OR_EQUAL,    BigIntegerGreaterOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.BYTE_TYPE,          Operator.LESS,                ByteLessEvaluator.INSTANCE );
+            addEvaluator( ValueType.BYTE_TYPE,          Operator.LESS_OR_EQUAL,       ByteLessOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.BYTE_TYPE,          Operator.GREATER,             ByteGreaterEvaluator.INSTANCE );
+            addEvaluator( ValueType.BYTE_TYPE,          Operator.GREATER_OR_EQUAL,    ByteGreaterOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PBYTE_TYPE,         Operator.LESS,                ByteLessEvaluator.INSTANCE );
+            addEvaluator( ValueType.PBYTE_TYPE,         Operator.LESS_OR_EQUAL,       ByteLessOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PBYTE_TYPE,         Operator.GREATER,             ByteGreaterEvaluator.INSTANCE );
+            addEvaluator( ValueType.PBYTE_TYPE,         Operator.GREATER_OR_EQUAL,    ByteGreaterOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.CHAR_TYPE,          Operator.LESS,                CharacterLessEvaluator.INSTANCE );
+            addEvaluator( ValueType.CHAR_TYPE,          Operator.LESS_OR_EQUAL,       CharacterLessOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.CHAR_TYPE,          Operator.GREATER,             CharacterGreaterEvaluator.INSTANCE );
+            addEvaluator( ValueType.CHAR_TYPE,          Operator.GREATER_OR_EQUAL,    CharacterGreaterOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PCHAR_TYPE,         Operator.LESS,                CharacterLessEvaluator.INSTANCE );
+            addEvaluator( ValueType.PCHAR_TYPE,         Operator.LESS_OR_EQUAL,       CharacterLessOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PCHAR_TYPE,         Operator.GREATER,             CharacterGreaterEvaluator.INSTANCE );
+            addEvaluator( ValueType.PCHAR_TYPE,         Operator.GREATER_OR_EQUAL,    CharacterGreaterOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.DATE_TYPE,          Operator.LESS,                DateLessEvaluator.INSTANCE );
+            addEvaluator( ValueType.DATE_TYPE,          Operator.LESS_OR_EQUAL,       DateLessOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.DATE_TYPE,          Operator.GREATER,             DateGreaterEvaluator.INSTANCE );
+            addEvaluator( ValueType.DATE_TYPE,          Operator.GREATER_OR_EQUAL,    DateGreaterOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.DOUBLE_TYPE,        Operator.LESS,                DoubleLessEvaluator.INSTANCE );
+            addEvaluator( ValueType.DOUBLE_TYPE,        Operator.LESS_OR_EQUAL,       DoubleLessOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.DOUBLE_TYPE,        Operator.GREATER,             DoubleGreaterEvaluator.INSTANCE );
+            addEvaluator( ValueType.DOUBLE_TYPE,        Operator.GREATER_OR_EQUAL,    DoubleGreaterOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PDOUBLE_TYPE,       Operator.LESS,                DoubleLessEvaluator.INSTANCE );
+            addEvaluator( ValueType.PDOUBLE_TYPE,       Operator.LESS_OR_EQUAL,       DoubleLessOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PDOUBLE_TYPE,       Operator.GREATER,             DoubleGreaterEvaluator.INSTANCE );
+            addEvaluator( ValueType.PDOUBLE_TYPE,       Operator.GREATER_OR_EQUAL,    DoubleGreaterOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.FLOAT_TYPE,         Operator.LESS,                FloatLessEvaluator.INSTANCE );
+            addEvaluator( ValueType.FLOAT_TYPE,         Operator.LESS_OR_EQUAL,       FloatLessOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.FLOAT_TYPE,         Operator.GREATER,             FloatGreaterEvaluator.INSTANCE );
+            addEvaluator( ValueType.FLOAT_TYPE,         Operator.GREATER_OR_EQUAL,    FloatGreaterOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PFLOAT_TYPE,        Operator.LESS,                FloatLessEvaluator.INSTANCE );
+            addEvaluator( ValueType.PFLOAT_TYPE,        Operator.LESS_OR_EQUAL,       FloatLessOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PFLOAT_TYPE,        Operator.GREATER,             FloatGreaterEvaluator.INSTANCE );
+            addEvaluator( ValueType.PFLOAT_TYPE,        Operator.GREATER_OR_EQUAL,    FloatGreaterOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.INTEGER_TYPE,       Operator.LESS,                IntegerLessEvaluator.INSTANCE );
+            addEvaluator( ValueType.INTEGER_TYPE,       Operator.LESS_OR_EQUAL,       IntegerLessOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.INTEGER_TYPE,       Operator.GREATER,             IntegerGreaterEvaluator.INSTANCE );
+            addEvaluator( ValueType.INTEGER_TYPE,       Operator.GREATER_OR_EQUAL,    IntegerGreaterOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PINTEGER_TYPE,      Operator.LESS,                IntegerLessEvaluator.INSTANCE );
+            addEvaluator( ValueType.PINTEGER_TYPE,      Operator.LESS_OR_EQUAL,       IntegerLessOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PINTEGER_TYPE,      Operator.GREATER,             IntegerGreaterEvaluator.INSTANCE );
+            addEvaluator( ValueType.PINTEGER_TYPE,      Operator.GREATER_OR_EQUAL,    IntegerGreaterOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.LONG_TYPE,          Operator.LESS,                LongLessEvaluator.INSTANCE );
+            addEvaluator( ValueType.LONG_TYPE,          Operator.LESS_OR_EQUAL,       LongLessOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.LONG_TYPE,          Operator.GREATER,             LongGreaterEvaluator.INSTANCE );
+            addEvaluator( ValueType.LONG_TYPE,          Operator.GREATER_OR_EQUAL,    LongGreaterOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PLONG_TYPE,         Operator.LESS,                LongLessEvaluator.INSTANCE );
+            addEvaluator( ValueType.PLONG_TYPE,         Operator.LESS_OR_EQUAL,       LongLessOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PLONG_TYPE,         Operator.GREATER,             LongGreaterEvaluator.INSTANCE );
+            addEvaluator( ValueType.PLONG_TYPE,         Operator.GREATER_OR_EQUAL,    LongGreaterOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.OBJECT_TYPE,        Operator.LESS,                ObjectLessEvaluator.INSTANCE );
+            addEvaluator( ValueType.OBJECT_TYPE,        Operator.LESS_OR_EQUAL,       ObjectLessOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.OBJECT_TYPE,        Operator.GREATER,             ObjectGreaterEvaluator.INSTANCE );
+            addEvaluator( ValueType.OBJECT_TYPE,        Operator.GREATER_OR_EQUAL,    ObjectGreaterOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.SHORT_TYPE,         Operator.LESS,                ShortLessEvaluator.INSTANCE );
+            addEvaluator( ValueType.SHORT_TYPE,         Operator.LESS_OR_EQUAL,       ShortLessOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.SHORT_TYPE,         Operator.GREATER,             ShortGreaterEvaluator.INSTANCE );
+            addEvaluator( ValueType.SHORT_TYPE,         Operator.GREATER_OR_EQUAL,    ShortGreaterOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PSHORT_TYPE,        Operator.LESS,                ShortLessEvaluator.INSTANCE );
+            addEvaluator( ValueType.PSHORT_TYPE,        Operator.LESS_OR_EQUAL,       ShortLessOrEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PSHORT_TYPE,        Operator.GREATER,             ShortGreaterEvaluator.INSTANCE );
+            addEvaluator( ValueType.PSHORT_TYPE,        Operator.GREATER_OR_EQUAL,    ShortGreaterOrEqualEvaluator.INSTANCE );
+        }
+    };
+    
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator) {
+        return this.evaluators.getEvaluator( type,
+                                             operator );
+    }
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator,
+                                  String parameterText) {
+        return this.evaluators.getEvaluator( type,
+                                             operator );
+    }
+
+    public Evaluator getEvaluator(final ValueType type,
+                                  final String operatorId,
+                                  final boolean isNegated,
+                                  final String parameterText) {
+        return this.evaluators.getEvaluator( type, 
+                                             Operator.determineOperator( operatorId, 
+                                                                         isNegated ) );
+    }
+
+    public String[] getEvaluatorIds() {
+        return SUPPORTED_IDS;
+    }
+
+    public boolean isNegatable() {
+        return false;
+    }
+
+    public boolean operatesOnFactHandles() {
+        return false;
+    }
+
+    public boolean supportsType(ValueType type) {
+        return this.evaluators.supportsType( type );
+    }
+    
+    /*  *********************************************************
+     *           Evaluator Implementations
+     *  *********************************************************
+     */
+    static class BigDecimalLessEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new BigDecimalLessEvaluator();
+
+        private BigDecimalLessEvaluator() {
+            super( ValueType.BIG_DECIMAL_TYPE,
+                   Operator.LESS );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final BigDecimal comp = (BigDecimal) extractor.getValue( workingMemory, object1 );
+            return comp.compareTo( (BigDecimal) object2.getValue() ) < 0;
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            final BigDecimal comp = (BigDecimal) ((ObjectVariableContextEntry) context).right;
+            return comp.compareTo( (BigDecimal) context.declaration.getExtractor().getValue( workingMemory, left ) ) < 0;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            final BigDecimal comp = (BigDecimal) context.extractor.getValue( workingMemory, right );
+            return comp.compareTo( (BigDecimal) ((ObjectVariableContextEntry) context).left ) < 0;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final BigDecimal comp = (BigDecimal) extractor1.getValue( workingMemory, object1 );
+            return comp.compareTo( (BigDecimal) extractor2.getValue( workingMemory, object2 ) ) < 0;
+        }
+
+        public String toString() {
+            return "BigDecimal <";
+        }
+    }
+
+    static class BigDecimalLessOrEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new BigDecimalLessOrEqualEvaluator();
+
+        private BigDecimalLessOrEqualEvaluator() {
+            super( ValueType.BIG_DECIMAL_TYPE,
+                   Operator.LESS_OR_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final BigDecimal comp = (BigDecimal) extractor.getValue( workingMemory, object1 );
+            return comp.compareTo( (BigDecimal) object2.getValue() ) <= 0;
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            final BigDecimal comp = (BigDecimal) ((ObjectVariableContextEntry) context).right;
+            return comp.compareTo( (BigDecimal) context.declaration.getExtractor().getValue( workingMemory, left ) ) <= 0;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            final BigDecimal comp = (BigDecimal) context.extractor.getValue( workingMemory, right );
+            return comp.compareTo( (BigDecimal) ((ObjectVariableContextEntry) context).left ) <= 0;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final BigDecimal comp = (BigDecimal) extractor1.getValue( workingMemory, object1 );
+            return comp.compareTo( (BigDecimal) extractor2.getValue( workingMemory, object2 ) ) <= 0;
+        }
+
+        public String toString() {
+            return "BigDecimal <=";
+        }
+    }
+
+    static class BigDecimalGreaterEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new BigDecimalGreaterEvaluator();
+
+        private BigDecimalGreaterEvaluator() {
+            super( ValueType.BIG_DECIMAL_TYPE,
+                   Operator.GREATER );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final BigDecimal comp = (BigDecimal) extractor.getValue( workingMemory, object1 );
+            return comp.compareTo( (BigDecimal) object2.getValue() ) > 0;
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            final BigDecimal comp = (BigDecimal) ((ObjectVariableContextEntry) context).right;
+            return comp.compareTo( (BigDecimal) context.declaration.getExtractor().getValue( workingMemory, left ) ) > 0;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            final BigDecimal comp = (BigDecimal) context.extractor.getValue( workingMemory, right );
+            return comp.compareTo( (BigDecimal) ((ObjectVariableContextEntry) context).left ) > 0;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final BigDecimal comp = (BigDecimal) extractor1.getValue( workingMemory, object1 );
+            return comp.compareTo( (BigDecimal) extractor2.getValue( workingMemory, object2 ) ) > 0;
+        }
+
+        public String toString() {
+            return "BigDecimal >";
+        }
+    }
+
+    static class BigDecimalGreaterOrEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long      serialVersionUID = 400L;
+        private final static Evaluator INSTANCE         = new BigDecimalGreaterOrEqualEvaluator();
+
+        private BigDecimalGreaterOrEqualEvaluator() {
+            super( ValueType.BIG_DECIMAL_TYPE,
+                   Operator.GREATER_OR_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final BigDecimal comp = (BigDecimal) extractor.getValue( workingMemory, object1 );
+            return comp.compareTo( (BigDecimal) object2.getValue() ) >= 0;
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            final BigDecimal comp = (BigDecimal) ((ObjectVariableContextEntry) context).right;
+            return comp.compareTo( (BigDecimal) context.declaration.getExtractor().getValue( workingMemory, left ) ) >= 0;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            final BigDecimal comp = (BigDecimal) context.extractor.getValue( workingMemory, right );
+            return comp.compareTo( (BigDecimal) ((ObjectVariableContextEntry) context).left ) >= 0;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final BigDecimal comp = (BigDecimal) extractor1.getValue( workingMemory, object1 );
+            return comp.compareTo( (BigDecimal) extractor2.getValue( workingMemory, object2 ) ) >= 0;
+        }
+
+        public String toString() {
+            return "BigDecimal >=";
+        }
+    }
+
+    static class BigIntegerLessEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new BigIntegerLessEvaluator();
+
+        private BigIntegerLessEvaluator() {
+            super( ValueType.BIG_INTEGER_TYPE,
+                   Operator.LESS );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final BigInteger comp = (BigInteger) extractor.getValue( workingMemory, object1 );
+            return comp.compareTo( (BigInteger) object2.getValue() ) < 0;
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            final BigInteger comp = (BigInteger) ((ObjectVariableContextEntry) context).right;
+            return comp.compareTo( (BigInteger) context.declaration.getExtractor().getValue( workingMemory, left ) ) < 0;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            final BigInteger comp = (BigInteger) context.extractor.getValue( workingMemory, right );
+            return comp.compareTo( (BigInteger) ((ObjectVariableContextEntry) context).left ) < 0;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final BigInteger comp = (BigInteger) extractor1.getValue( workingMemory, object1 );
+            return comp.compareTo( (BigInteger) extractor2.getValue( workingMemory, object2 ) ) < 0;
+        }
+
+        public String toString() {
+            return "BigInteger <";
+        }
+    }
+
+    static class BigIntegerLessOrEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new BigIntegerLessOrEqualEvaluator();
+
+        private BigIntegerLessOrEqualEvaluator() {
+            super( ValueType.BIG_INTEGER_TYPE,
+                   Operator.LESS_OR_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final BigInteger comp = (BigInteger) extractor.getValue( workingMemory, object1 );
+            return comp.compareTo( (BigInteger) object2.getValue() ) <= 0;
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            final BigInteger comp = (BigInteger) ((ObjectVariableContextEntry) context).right;
+            return comp.compareTo( (BigInteger) context.declaration.getExtractor().getValue( workingMemory, left ) ) <= 0;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            final BigInteger comp = (BigInteger) context.extractor.getValue( workingMemory, right );
+            return comp.compareTo( (BigInteger) ((ObjectVariableContextEntry) context).left ) <= 0;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final BigInteger comp = (BigInteger) extractor1.getValue( workingMemory, object1 );
+            return comp.compareTo( (BigInteger) extractor2.getValue( workingMemory, object2 ) ) <= 0;
+        }
+
+        public String toString() {
+            return "BigInteger <=";
+        }
+    }
+
+    static class BigIntegerGreaterEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new BigIntegerGreaterEvaluator();
+
+        private BigIntegerGreaterEvaluator() {
+            super( ValueType.BIG_INTEGER_TYPE,
+                   Operator.GREATER );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final BigInteger comp = (BigInteger) extractor.getValue( workingMemory, object1 );
+            return comp.compareTo( (BigInteger) object2.getValue() ) > 0;
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            final BigInteger comp = (BigInteger) ((ObjectVariableContextEntry) context).right;
+            return comp.compareTo( (BigInteger) context.declaration.getExtractor().getValue( workingMemory, left ) ) > 0;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            final BigInteger comp = (BigInteger) context.extractor.getValue( workingMemory, right );
+            return comp.compareTo( (BigInteger) ((ObjectVariableContextEntry) context).left ) > 0;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final BigInteger comp = (BigInteger) extractor1.getValue( workingMemory, object1 );
+            return comp.compareTo( (BigInteger) extractor2.getValue( workingMemory, object2 ) ) > 0;
+        }
+
+        public String toString() {
+            return "BigInteger >";
+        }
+    }
+
+    static class BigIntegerGreaterOrEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long      serialVersionUID = 400L;
+        private final static Evaluator INSTANCE         = new BigIntegerGreaterOrEqualEvaluator();
+
+        private BigIntegerGreaterOrEqualEvaluator() {
+            super( ValueType.BIG_INTEGER_TYPE,
+                   Operator.GREATER_OR_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final BigInteger comp = (BigInteger) extractor.getValue( workingMemory, object1 );
+            return comp.compareTo( (BigInteger) object2.getValue() ) >= 0;
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            final BigInteger comp = (BigInteger) ((ObjectVariableContextEntry) context).right;
+            return comp.compareTo( (BigInteger) context.declaration.getExtractor().getValue( workingMemory, left ) ) >= 0;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            final BigInteger comp = (BigInteger) context.extractor.getValue( workingMemory, right );
+            return comp.compareTo( (BigInteger) ((ObjectVariableContextEntry) context).left ) >= 0;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final BigInteger comp = (BigInteger) extractor1.getValue( workingMemory, object1 );
+            return comp.compareTo( (BigInteger) extractor2.getValue( workingMemory, object2 ) ) >= 0;
+        }
+
+        public String toString() {
+            return "BigInteger >=";
+        }
+    }
+    
+    static class ByteLessEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ByteLessEvaluator();
+
+        private ByteLessEvaluator() {
+            super( ValueType.PBYTE_TYPE,
+                   Operator.LESS );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor.getByteValue( workingMemory, object1 ) < object2.getByteValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            return ((LongVariableContextEntry) context).right < context.declaration.getExtractor().getByteValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            return context.extractor.getByteValue( workingMemory, right ) < ((LongVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor1.getByteValue( workingMemory, object1 ) < extractor2.getByteValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Byte <";
+        }
+    }
+
+    static class ByteLessOrEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ByteLessOrEqualEvaluator();
+
+        private ByteLessOrEqualEvaluator() {
+            super( ValueType.PBYTE_TYPE,
+                   Operator.LESS_OR_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor.getByteValue( workingMemory, object1 ) <= object2.getByteValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            return ((LongVariableContextEntry) context).right <= context.declaration.getExtractor().getByteValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            return context.extractor.getByteValue( workingMemory, right ) <= ((LongVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor1.getByteValue( workingMemory, object1 ) <= extractor2.getByteValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Byte <=";
+        }
+    }
+
+    static class ByteGreaterEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ByteGreaterEvaluator();
+
+        private ByteGreaterEvaluator() {
+            super( ValueType.PBYTE_TYPE,
+                   Operator.GREATER );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor.getByteValue( workingMemory, object1 ) > object2.getByteValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            return ((LongVariableContextEntry) context).right > context.declaration.getExtractor().getByteValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            return context.extractor.getByteValue( workingMemory, right ) > ((LongVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor1.getByteValue( workingMemory, object1 ) > extractor2.getByteValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Byte >";
+        }
+    }
+
+    static class ByteGreaterOrEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long      serialVersionUID = 400L;
+        private final static Evaluator INSTANCE         = new ByteGreaterOrEqualEvaluator();
+
+        private ByteGreaterOrEqualEvaluator() {
+            super( ValueType.PBYTE_TYPE,
+                   Operator.GREATER_OR_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor.getByteValue( workingMemory, object1 ) >= object2.getByteValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            return ((LongVariableContextEntry) context).right >= context.declaration.getExtractor().getByteValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            return context.extractor.getByteValue( workingMemory, right ) >= ((LongVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor1.getByteValue( workingMemory, object1 ) >= extractor2.getByteValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Byte >=";
+        }
+    }
+
+    static class CharacterLessEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new CharacterLessEvaluator();
+
+        private CharacterLessEvaluator() {
+            super( ValueType.PCHAR_TYPE,
+                   Operator.LESS );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor.getCharValue( workingMemory, object1 ) < object2.getCharValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            return ((CharVariableContextEntry) context).right < context.declaration.getExtractor().getCharValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            return context.extractor.getCharValue( workingMemory, right ) < ((CharVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor1.getCharValue( workingMemory, object1 ) < extractor2.getCharValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Character <";
+        }
+    }
+
+    static class CharacterLessOrEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new CharacterLessOrEqualEvaluator();
+
+        private CharacterLessOrEqualEvaluator() {
+            super( ValueType.PCHAR_TYPE,
+                   Operator.LESS_OR_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor.getCharValue( workingMemory, object1 ) <= object2.getCharValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            return ((CharVariableContextEntry) context).right <= context.declaration.getExtractor().getCharValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            return context.extractor.getCharValue( workingMemory, right ) <= ((CharVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor1.getCharValue( workingMemory, object1 ) <= extractor2.getCharValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Character <=";
+        }
+    }
+
+    static class CharacterGreaterEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new CharacterGreaterEvaluator();
+
+        private CharacterGreaterEvaluator() {
+            super( ValueType.PCHAR_TYPE,
+                   Operator.GREATER );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor.getCharValue( workingMemory, object1 ) > object2.getCharValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            return ((CharVariableContextEntry) context).right > context.declaration.getExtractor().getCharValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            return context.extractor.getCharValue( workingMemory, right ) > ((CharVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor1.getCharValue( workingMemory, object1 ) > extractor2.getCharValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Character >";
+        }
+    }
+
+    static class CharacterGreaterOrEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long      serialVersionUID = 400L;
+        private final static Evaluator INSTANCE         = new CharacterGreaterOrEqualEvaluator();
+
+        private CharacterGreaterOrEqualEvaluator() {
+            super( ValueType.PCHAR_TYPE,
+                   Operator.GREATER_OR_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor.getCharValue( workingMemory, object1 ) >= object2.getCharValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            return ((CharVariableContextEntry) context).right >= context.declaration.getExtractor().getCharValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            return context.extractor.getCharValue( workingMemory, right ) >= ((CharVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor1.getCharValue( workingMemory, object1 ) >= extractor2.getCharValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Character >=";
+        }
+    }
+
+    static class DateLessEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new DateLessEvaluator();
+
+        private DateLessEvaluator() {
+            super( ValueType.DATE_TYPE,
+                   Operator.LESS );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final Date value1 = (Date) extractor.getValue( workingMemory, object1 );
+            final Object value2 = object2.getValue();
+            return value1.compareTo( DateUtils.getRightDate( value2 ) ) < 0;
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            final Date value1 = (Date) context.declaration.getExtractor().getValue( workingMemory, left );
+            final Object value2 = ((ObjectVariableContextEntry) context).right;
+            return DateUtils.getRightDate( value2 ).compareTo( value1 ) < 0;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            final Date value1 = (Date) ((ObjectVariableContextEntry) context).left;
+            final Object value2 = context.extractor.getValue( workingMemory, right );
+            return DateUtils.getRightDate( value2 ).compareTo( value1 ) < 0;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final Date value1 = (Date) extractor1.getValue( workingMemory, object1 );
+            final Date value2 = (Date) extractor2.getValue( workingMemory, object2 );
+            return value1.compareTo( value2 ) < 0;
+        }
+
+        public String toString() {
+            return "Date <";
+        }
+    }
+
+    static class DateLessOrEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new DateLessOrEqualEvaluator();
+
+        private DateLessOrEqualEvaluator() {
+            super( ValueType.DATE_TYPE,
+                   Operator.LESS_OR_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final Date value1 = (Date) extractor.getValue( workingMemory, object1 );
+            final Object value2 = object2.getValue();
+            return value1.compareTo( DateUtils.getRightDate( value2 ) ) <= 0;
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            final Date value1 = (Date) context.declaration.getExtractor().getValue( workingMemory, left );
+            final Object value2 = ((ObjectVariableContextEntry) context).right;
+            return DateUtils.getRightDate( value2 ).compareTo( value1 ) <= 0;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            final Date value1 = (Date) ((ObjectVariableContextEntry) context).left;
+            final Object value2 = context.extractor.getValue( workingMemory, right );
+            return DateUtils.getRightDate( value2 ).compareTo( value1 ) <= 0;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final Date value1 = (Date) extractor1.getValue( workingMemory, object1 );
+            final Date value2 = (Date) extractor2.getValue( workingMemory, object2 );
+            return value1.compareTo( value2 ) <= 0;
+        }
+
+        public String toString() {
+            return "Date <=";
+        }
+    }
+
+    static class DateGreaterEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new DateGreaterEvaluator();
+
+        private DateGreaterEvaluator() {
+            super( ValueType.DATE_TYPE,
+                   Operator.GREATER );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final Date value1 = (Date) extractor.getValue( workingMemory, object1 );
+            final Object value2 = object2.getValue();
+            return value1.compareTo( DateUtils.getRightDate( value2 ) ) > 0;
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            final Date value1 = (Date) context.declaration.getExtractor().getValue( workingMemory, left );
+            final Object value2 = ((ObjectVariableContextEntry) context).right;
+            return DateUtils.getRightDate( value2 ).compareTo( value1 ) > 0;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            final Date value1 = (Date) ((ObjectVariableContextEntry) context).left;
+            final Object value2 = context.extractor.getValue( workingMemory, right );
+            return DateUtils.getRightDate( value2 ).compareTo( value1 ) > 0;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final Date value1 = (Date) extractor1.getValue( workingMemory, object1 );
+            final Date value2 = (Date) extractor2.getValue( workingMemory, object2 );
+            return value1.compareTo( value2 ) > 0;
+        }
+
+        public String toString() {
+            return "Date >";
+        }
+    }
+
+    static class DateGreaterOrEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long      serialVersionUID = 400L;
+        private final static Evaluator INSTANCE         = new DateGreaterOrEqualEvaluator();
+
+        private DateGreaterOrEqualEvaluator() {
+            super( ValueType.DATE_TYPE,
+                   Operator.GREATER_OR_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final Date value1 = (Date) extractor.getValue( workingMemory, object1 );
+            final Object value2 = object2.getValue();
+            return value1.compareTo( DateUtils.getRightDate( value2 ) ) >= 0;
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            final Date value1 = (Date) context.declaration.getExtractor().getValue( workingMemory, left );
+            final Object value2 = ((ObjectVariableContextEntry) context).right;
+            return DateUtils.getRightDate( value2 ).compareTo( value1 ) >= 0;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            final Date value1 = (Date) ((ObjectVariableContextEntry) context).left;
+            final Object value2 = context.extractor.getValue( workingMemory, right );
+            return DateUtils.getRightDate( value2 ).compareTo( value1 ) >= 0;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final Date value1 = (Date) extractor1.getValue( workingMemory, object1 );
+            final Date value2 = (Date) extractor2.getValue( workingMemory, object2 );
+            return value1.compareTo( value2 ) >= 0;
+        }
+
+        public String toString() {
+            return "Date >=";
+        }
+    }
+
+    static class DoubleLessEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new DoubleLessEvaluator();
+
+        private DoubleLessEvaluator() {
+            super( ValueType.PDOUBLE_TYPE,
+                   Operator.LESS );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor.getDoubleValue( workingMemory, object1 ) < object2.getDoubleValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return ((DoubleVariableContextEntry) context).right < context.declaration.getExtractor().getDoubleValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return context.extractor.getDoubleValue( workingMemory, right ) < ((DoubleVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor1.getDoubleValue( workingMemory, object1 ) < extractor2.getDoubleValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Double <";
+        }
+    }
+
+    static class DoubleLessOrEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new DoubleLessOrEqualEvaluator();
+
+        private DoubleLessOrEqualEvaluator() {
+            super( ValueType.PDOUBLE_TYPE,
+                   Operator.LESS_OR_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor.getDoubleValue( workingMemory, object1 ) <= object2.getDoubleValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return ((DoubleVariableContextEntry) context).right <= context.declaration.getExtractor().getDoubleValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return context.extractor.getDoubleValue( workingMemory, right ) <= ((DoubleVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor1.getDoubleValue( workingMemory, object1 ) <= extractor2.getDoubleValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Double <=";
+        }
+    }
+
+    static class DoubleGreaterEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new DoubleGreaterEvaluator();
+
+        private DoubleGreaterEvaluator() {
+            super( ValueType.PDOUBLE_TYPE,
+                   Operator.GREATER );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor.getDoubleValue( workingMemory, object1 ) > object2.getDoubleValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return ((DoubleVariableContextEntry) context).right > context.declaration.getExtractor().getDoubleValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return context.extractor.getDoubleValue( workingMemory, right ) > ((DoubleVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor1.getDoubleValue( workingMemory, object1 ) > extractor2.getDoubleValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Double >";
+        }
+    }
+
+    static class DoubleGreaterOrEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long      serialVersionUID = 400L;
+        private final static Evaluator INSTANCE         = new DoubleGreaterOrEqualEvaluator();
+
+        private DoubleGreaterOrEqualEvaluator() {
+            super( ValueType.PDOUBLE_TYPE,
+                   Operator.GREATER_OR_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor.getDoubleValue( workingMemory, object1 ) >= object2.getDoubleValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return ((DoubleVariableContextEntry) context).right >= context.declaration.getExtractor().getDoubleValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return context.extractor.getDoubleValue( workingMemory, right ) >= ((DoubleVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor1.getDoubleValue( workingMemory, object1 ) >= extractor2.getDoubleValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Double >=";
+        }
+    }
+    
+    static class FloatLessEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new FloatLessEvaluator();
+
+        private FloatLessEvaluator() {
+            super( ValueType.PFLOAT_TYPE,
+                   Operator.LESS );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor.getFloatValue( workingMemory, object1 ) < object2.getFloatValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return ((DoubleVariableContextEntry) context).right < context.declaration.getExtractor().getFloatValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return context.extractor.getFloatValue( workingMemory, right ) < ((DoubleVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor1.getFloatValue( workingMemory, object1 ) < extractor2.getFloatValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Float <";
+        }
+    }
+
+    static class FloatLessOrEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new FloatLessOrEqualEvaluator();
+
+        private FloatLessOrEqualEvaluator() {
+            super( ValueType.PFLOAT_TYPE,
+                   Operator.LESS_OR_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor.getFloatValue( workingMemory, object1 ) <= object2.getFloatValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return ((DoubleVariableContextEntry) context).right <= context.declaration.getExtractor().getFloatValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return context.extractor.getFloatValue( workingMemory, right ) <= ((DoubleVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor1.getFloatValue( workingMemory, object1 ) <= extractor2.getFloatValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Float <=";
+        }
+    }
+
+    static class FloatGreaterEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new FloatGreaterEvaluator();
+
+        private FloatGreaterEvaluator() {
+            super( ValueType.PFLOAT_TYPE,
+                   Operator.GREATER );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor.getFloatValue( workingMemory, object1 ) > object2.getFloatValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return ((DoubleVariableContextEntry) context).right > context.declaration.getExtractor().getFloatValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return context.extractor.getFloatValue( workingMemory, right ) > ((DoubleVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor1.getFloatValue( workingMemory, object1 ) > extractor2.getFloatValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Float >";
+        }
+    }
+
+    static class FloatGreaterOrEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long      serialVersionUID = 400L;
+        private final static Evaluator INSTANCE         = new FloatGreaterOrEqualEvaluator();
+
+        private FloatGreaterOrEqualEvaluator() {
+            super( ValueType.PFLOAT_TYPE,
+                   Operator.GREATER_OR_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor.getFloatValue( workingMemory, object1 ) >= object2.getFloatValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return ((DoubleVariableContextEntry) context).right >= context.declaration.getExtractor().getFloatValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return context.extractor.getFloatValue( workingMemory, right ) >= ((DoubleVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor1.getFloatValue( workingMemory, object1 ) >= extractor2.getFloatValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Float >=";
+        }
+    }
+    
+    static class IntegerLessEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new IntegerLessEvaluator();
+
+        private IntegerLessEvaluator() {
+            super( ValueType.PINTEGER_TYPE,
+                   Operator.LESS );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor.getIntValue( workingMemory, object1 ) < object2.getIntValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            return ((LongVariableContextEntry) context).right < context.declaration.getExtractor().getIntValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            return context.extractor.getIntValue( workingMemory, right ) < ((LongVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor1.getIntValue( workingMemory, object1 ) < extractor2.getIntValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Integer <";
+        }
+    }
+
+    static class IntegerLessOrEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new IntegerLessOrEqualEvaluator();
+
+        private IntegerLessOrEqualEvaluator() {
+            super( ValueType.PINTEGER_TYPE,
+                   Operator.LESS_OR_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor.getIntValue( workingMemory, object1 ) <= object2.getIntValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            return ((LongVariableContextEntry) context).right <= context.declaration.getExtractor().getIntValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            return context.extractor.getIntValue( workingMemory, right ) <= ((LongVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor1.getIntValue( workingMemory, object1 ) <= extractor2.getIntValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Integer <=";
+        }
+    }
+
+    static class IntegerGreaterEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new IntegerGreaterEvaluator();
+
+        private IntegerGreaterEvaluator() {
+            super( ValueType.PINTEGER_TYPE,
+                   Operator.GREATER );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor.getIntValue( workingMemory, object1 ) > object2.getIntValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            return ((LongVariableContextEntry) context).right > context.declaration.getExtractor().getIntValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            return context.extractor.getIntValue( workingMemory, right ) > ((LongVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor1.getIntValue( workingMemory, object1 ) > extractor2.getIntValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Integer >";
+        }
+    }
+
+    static class IntegerGreaterOrEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long      serialVersionUID = 400L;
+        private final static Evaluator INSTANCE         = new IntegerGreaterOrEqualEvaluator();
+
+        private IntegerGreaterOrEqualEvaluator() {
+            super( ValueType.PINTEGER_TYPE,
+                   Operator.GREATER_OR_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor.getIntValue( workingMemory, object1 ) >= object2.getIntValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            return ((LongVariableContextEntry) context).right >= context.declaration.getExtractor().getIntValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            return context.extractor.getIntValue( workingMemory, right ) >= ((LongVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor1.getIntValue( workingMemory, object1 ) >= extractor2.getIntValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Integer >=";
+        }
+    }
+    
+    static class LongLessEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new LongLessEvaluator();
+
+        private LongLessEvaluator() {
+            super( ValueType.PLONG_TYPE,
+                   Operator.LESS );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor.getLongValue( workingMemory, object1 ) < object2.getLongValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            return ((LongVariableContextEntry) context).right < context.declaration.getExtractor().getLongValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            return context.extractor.getLongValue( workingMemory, right ) < ((LongVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor1.getLongValue( workingMemory, object1 ) < extractor2.getLongValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Long <";
+        }
+    }
+
+    static class LongLessOrEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new LongLessOrEqualEvaluator();
+
+        private LongLessOrEqualEvaluator() {
+            super( ValueType.PLONG_TYPE,
+                   Operator.LESS_OR_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor.getLongValue( workingMemory, object1 ) <= object2.getLongValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            return ((LongVariableContextEntry) context).right <= context.declaration.getExtractor().getLongValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            return context.extractor.getLongValue( workingMemory, right ) <= ((LongVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor1.getLongValue( workingMemory, object1 ) <= extractor2.getLongValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Long <=";
+        }
+    }
+
+    static class LongGreaterEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new LongGreaterEvaluator();
+
+        private LongGreaterEvaluator() {
+            super( ValueType.PLONG_TYPE,
+                   Operator.GREATER );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor.getLongValue( workingMemory, object1 ) > object2.getLongValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            return ((LongVariableContextEntry) context).right > context.declaration.getExtractor().getLongValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            return context.extractor.getLongValue( workingMemory, right ) > ((LongVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor1.getLongValue( workingMemory, object1 ) > extractor2.getLongValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Long >";
+        }
+    }
+
+    static class LongGreaterOrEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long      serialVersionUID = 400L;
+        private final static Evaluator INSTANCE         = new LongGreaterOrEqualEvaluator();
+
+        private LongGreaterOrEqualEvaluator() {
+            super( ValueType.PLONG_TYPE,
+                   Operator.GREATER_OR_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor.getLongValue( workingMemory, object1 ) >= object2.getLongValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            return ((LongVariableContextEntry) context).right >= context.declaration.getExtractor().getLongValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            return context.extractor.getLongValue( workingMemory, right ) >= ((LongVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor1.getLongValue( workingMemory, object1 ) >= extractor2.getLongValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Long >=";
+        }
+    }
+    
+    static class ObjectLessEvaluator extends BaseEvaluator {
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ObjectLessEvaluator();
+        private static final ObjectComparator comparator = new ObjectComparator();
+        
+
+        private ObjectLessEvaluator() {
+            super( ValueType.OBJECT_TYPE,
+                   Operator.LESS );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final Comparable comp = (Comparable) extractor.getValue( workingMemory, object1 );
+            return comparator.compare( comp, object2.getValue() ) < 0;
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            final Comparable comp = (Comparable) ((ObjectVariableContextEntry) context).right;
+            return comparator.compare( comp,  context.declaration.getExtractor().getValue( workingMemory, left ) ) < 0;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            final Comparable comp = (Comparable) context.extractor.getValue( workingMemory, right );
+            return comparator.compare( comp, ((ObjectVariableContextEntry) context).left ) < 0;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final Comparable comp = (Comparable) extractor1.getValue( workingMemory, object1 );
+            return comparator.compare( comp, extractor2.getValue( workingMemory, object2 ) ) < 0;
+        }
+
+        public String toString() {
+            return "Object <";
+        }
+    }
+
+    static class ObjectLessOrEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ObjectLessOrEqualEvaluator();
+        private static final ObjectComparator comparator = new ObjectComparator();
+
+        private ObjectLessOrEqualEvaluator() {
+            super( ValueType.OBJECT_TYPE,
+                   Operator.LESS_OR_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final Comparable comp = (Comparable) extractor.getValue( workingMemory, object1 );
+            return comparator.compare( comp, object2.getValue() ) <= 0;
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            final Comparable comp = (Comparable) ((ObjectVariableContextEntry) context).right;
+            return comparator.compare( comp, context.declaration.getExtractor().getValue( workingMemory, left ) ) <= 0;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            final Comparable comp = (Comparable) context.extractor.getValue( workingMemory, right );
+            return comparator.compare( comp, ((ObjectVariableContextEntry) context).left ) <= 0;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final Comparable comp = (Comparable) extractor1.getValue( workingMemory, object1 );
+            return comparator.compare( comp, extractor2.getValue( workingMemory, object2 ) ) <= 0;
+        }
+
+        public String toString() {
+            return "Object <=";
+        }
+    }
+
+    static class ObjectGreaterEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ObjectGreaterEvaluator();
+        private static final ObjectComparator comparator = new ObjectComparator();
+
+        private ObjectGreaterEvaluator() {
+            super( ValueType.OBJECT_TYPE,
+                   Operator.GREATER );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final Comparable comp = (Comparable) extractor.getValue( workingMemory, object1 );
+            return comparator.compare( comp, object2.getValue() ) > 0;
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            final Comparable comp = (Comparable) ((ObjectVariableContextEntry) context).right;
+            return comparator.compare( comp, context.declaration.getExtractor().getValue( workingMemory, left ) ) > 0;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            final Comparable comp = (Comparable) context.extractor.getValue( workingMemory, right );
+            return comparator.compare( comp, ((ObjectVariableContextEntry) context).left ) > 0;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final Comparable comp = (Comparable) extractor1.getValue( workingMemory, object1 );
+            return comparator.compare( comp, extractor2.getValue( workingMemory, object2 ) ) > 0;
+        }
+
+        public String toString() {
+            return "Object >";
+        }
+    }
+
+    static class ObjectGreaterOrEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ObjectGreaterOrEqualEvaluator();
+        private static final ObjectComparator comparator = new ObjectComparator();
+
+        private ObjectGreaterOrEqualEvaluator() {
+            super( ValueType.OBJECT_TYPE,
+                   Operator.GREATER_OR_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final Comparable comp = (Comparable) extractor.getValue( workingMemory, object1 );
+            return comparator.compare( comp, object2.getValue() ) >= 0;
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            final Comparable comp = (Comparable) ((ObjectVariableContextEntry) context).right;
+            return comparator.compare( comp, context.declaration.getExtractor().getValue( workingMemory, left ) ) >= 0;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            final Comparable comp = (Comparable) context.extractor.getValue( workingMemory, right );
+            return comparator.compare( comp, ((ObjectVariableContextEntry) context).left ) >= 0;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            final Comparable comp = (Comparable) extractor1.getValue( workingMemory, object1 );
+            return comparator.compare( comp, extractor2.getValue( workingMemory, object2 ) ) >= 0;
+        }
+
+        public String toString() {
+            return "Object >=";
+        }
+    }
+
+    static class ShortLessEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long      serialVersionUID = 400L;
+        private static final Evaluator INSTANCE         = new ShortLessEvaluator();
+
+        private ShortLessEvaluator() {
+            super( ValueType.PSHORT_TYPE,
+                   Operator.LESS );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor.getShortValue( workingMemory, object1 ) < object2.getShortValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            return ((LongVariableContextEntry) context).right < context.declaration.getExtractor().getShortValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            return context.extractor.getShortValue( workingMemory, right ) < ((LongVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor1.getShortValue( workingMemory, object1 ) < extractor2.getShortValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Short <";
+        }
+    }
+
+    static class ShortLessOrEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long      serialVersionUID = 400L;
+        private static final Evaluator INSTANCE         = new ShortLessOrEqualEvaluator();
+
+        private ShortLessOrEqualEvaluator() {
+            super( ValueType.PSHORT_TYPE,
+                   Operator.LESS_OR_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor.getShortValue( workingMemory, object1 ) <= object2.getShortValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            return ((LongVariableContextEntry) context).right <= context.declaration.getExtractor().getShortValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            return context.extractor.getShortValue( workingMemory, right ) <= ((LongVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor1.getShortValue( workingMemory, object1 ) <= extractor2.getShortValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Boolean <=";
+        }
+    }
+
+    static class ShortGreaterEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long      serialVersionUID = 400L;
+        private static final Evaluator INSTANCE         = new ShortGreaterEvaluator();
+
+        private ShortGreaterEvaluator() {
+            super( ValueType.PSHORT_TYPE,
+                   Operator.GREATER );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor.getShortValue( workingMemory, object1 ) > object2.getShortValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            return ((LongVariableContextEntry) context).right > context.declaration.getExtractor().getShortValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            return context.extractor.getShortValue( workingMemory, right ) > ((LongVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor1.getShortValue( workingMemory, object1 ) > extractor2.getShortValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Short >";
+        }
+    }
+
+    static class ShortGreaterOrEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long      serialVersionUID = 400L;
+        private static final Evaluator INSTANCE         = new ShortGreaterOrEqualEvaluator();
+
+        private ShortGreaterOrEqualEvaluator() {
+            super( ValueType.PSHORT_TYPE,
+                   Operator.GREATER_OR_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if( extractor.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor.getShortValue( workingMemory, object1 ) >= object2.getShortValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if( context.rightNull ) {
+                return false;
+            }
+            return ((LongVariableContextEntry) context).right >= context.declaration.getExtractor().getShortValue( workingMemory, left );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if( context.extractor.isNullValue( workingMemory, right ) ) {
+                return false;
+            }
+            return context.extractor.getShortValue( workingMemory, right ) >= ((LongVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if( extractor1.isNullValue( workingMemory, object1 ) ) {
+                return false;
+            }
+            return extractor1.getShortValue( workingMemory, object1 ) >= extractor2.getShortValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Short >=";
+        }
+    }
+
+    
+    protected static class ObjectComparator implements Comparator {
+        // this is a stateless object, and so, can be shared among threads
+        // PLEASE: do not add state to it, unless you remove all concurrent 
+        // calls to this class instances
+
+        public int compare(Object arg0,
+                           Object arg1) {
+            if( arg0 instanceof Double || arg0 instanceof Float ) {
+                double val0 = ((Number) arg0).doubleValue();
+                double val1 = 0;
+                if( arg1 instanceof Number ) {
+                    val1 = ((Number) arg1).doubleValue();
+                } else if( arg1 instanceof String ) {
+                    val1 = Double.parseDouble( ( String ) arg1 );
+                } else {
+                    throw new ClassCastException( "Not possible to convert "+arg1.getClass()+" into a double value to compare it to "+arg0.getClass() );
+                }
+                return val0 > val1 ? 1 : val0 < val1 ? -1 : 0;
+            } else if( arg0 instanceof Number ){
+                long val0 = ((Number) arg0).longValue();
+                long val1 = 0;
+                if( arg1 instanceof Number ) {
+                    val1 = ((Number) arg1).longValue();
+                } else if( arg1 instanceof String ) {
+                    val1 = Long.parseLong( ( String ) arg1 ); 
+                } else {
+                    throw new ClassCastException( "Not possible to convert "+arg1.getClass()+" into a long value to compare it to "+arg0.getClass() );
+                }
+                return val0 > val1 ? 1 : val0 < val1 ? -1 : 0;
+            } else if( arg0 instanceof String ) {
+                try {
+                    double val0 = Double.parseDouble( (String) arg0 );
+                    double val1 = 0;
+                    if( arg1 instanceof Number ) {
+                        val1 = ((Number) arg1).doubleValue();
+                    } else if( arg1 instanceof String ) {
+                        val1 = Double.parseDouble( ( String ) arg1 );
+                    } else {
+                        throw new ClassCastException( "Not possible to convert "+arg1.getClass()+" into a double value to compare it to "+arg0.getClass() );
+                    }
+                    return val0 > val1 ? 1 : val0 < val1 ? -1 : 0;
+                } catch( NumberFormatException nfe ) {
+                    return ( (String) arg0).compareTo( arg1.toString() );
+                }
+                
+            }
+            try {
+                return ((Comparable)arg0).compareTo( arg1 );
+            } catch ( ClassCastException cce ) {
+                throw new ClassCastException( "Not possible to compare a "+arg0.getClass()+" with a "+arg1.getClass());
+            }
+        }
+    }
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/DuringEvaluatorDefinition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/DuringEvaluatorDefinition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/DuringEvaluatorDefinition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 6, 2007
+ */
+package org.drools.base.evaluators;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.BaseEvaluator;
+import org.drools.base.ValueType;
+import org.drools.common.EventFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.VariableRestriction.ObjectVariableContextEntry;
+import org.drools.rule.VariableRestriction.VariableContextEntry;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldValue;
+
+/**
+ * The implementation of the 'during' evaluator definition
+ * 
+ * @author mgroch
+ */
+public class DuringEvaluatorDefinition
+    implements
+    EvaluatorDefinition {
+
+    public static final Operator  DURING       = Operator.addOperatorToRegistry( "during",
+                                                                                  false );
+    public static final Operator  NOT_DURING   = Operator.addOperatorToRegistry( "during",
+                                                                                  true );
+    
+    private static final String[] SUPPORTED_IDS = { DURING.getOperatorString() };
+    
+    private Map<String, DuringEvaluator> cache        = Collections.emptyMap();
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  null );
+    }
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator,
+                                  String parameterText) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  parameterText );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public Evaluator getEvaluator(final ValueType type,
+                                  final String operatorId,
+                                  final boolean isNegated,
+                                  final String parameterText) {
+        if ( this.cache == Collections.EMPTY_MAP ) {
+            this.cache = new HashMap<String, DuringEvaluator>();
+        }
+        String key = isNegated + ":" + parameterText;
+        DuringEvaluator eval = this.cache.get( key );
+        if ( eval == null ) {
+            eval = new DuringEvaluator( type,
+                                       isNegated,
+                                       parameterText );
+            this.cache.put( key,
+                            eval );
+        }
+        return eval;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public String[] getEvaluatorIds() {
+        return SUPPORTED_IDS;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean isNegatable() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean operatesOnFactHandles() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean supportsType(ValueType type) {
+        // supports all types, since it operates over fact handles
+        // Note: should we change this interface to allow checking of event classes only?
+        return true;
+    }
+
+    /**
+     * Implements the 'during' evaluator itself
+     */
+    public static class DuringEvaluator extends BaseEvaluator {
+		private static final long serialVersionUID = -5856043346192967722L;
+		
+		private long                  startMinDev, startMaxDev;
+        private long                  endMinDev, endMaxDev;
+
+        public DuringEvaluator(final ValueType type,
+                              final boolean isNegated,
+                              final String parameters) {
+            super( type,
+                   isNegated ? NOT_DURING : DURING );
+            this.parseParameters( parameters );
+        }
+        
+        @Override
+        public Object prepareObject(InternalFactHandle handle) {
+            return handle;
+        }
+        
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            throw new RuntimeDroolsException( "The 'during' operator can only be used to compare one event to another, and never to compare to literal constraints." );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                final VariableContextEntry context,
+                final Object left) {
+			
+        	if ( context.rightNull ) {
+        		return false;
+				}
+			long distStart = ((EventFactHandle)((ObjectVariableContextEntry) context).right).getStartTimestamp() - ((EventFactHandle) left ).getStartTimestamp();
+			long distEnd = ((EventFactHandle) left ).getEndTimestamp() - ((EventFactHandle)((ObjectVariableContextEntry) context).right).getEndTimestamp();
+			return this.getOperator().isNegated() ^ ( distStart >= this.startMinDev && distStart <= this.startMaxDev 
+					&& distEnd >= this.endMinDev && distEnd <= this.endMaxDev );
+		}
+			
+		public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+			               final VariableContextEntry context,
+			               final Object right) {
+			if ( context.extractor.isNullValue( workingMemory,
+			                     right ) ) {
+			return false;
+			}
+			long distStart = ((EventFactHandle) right ).getStartTimestamp() - ((EventFactHandle) ((ObjectVariableContextEntry) context).left).getStartTimestamp();
+			long distEnd = ((EventFactHandle) ((ObjectVariableContextEntry) context).left).getEndTimestamp() - ((EventFactHandle) right ).getEndTimestamp();
+			return this.getOperator().isNegated() ^ ( distStart >= this.startMinDev && distStart <= this.startMaxDev 
+					&& distEnd >= this.endMinDev && distEnd <= this.endMaxDev );
+		}
+			
+		public boolean evaluate(InternalWorkingMemory workingMemory,
+			     final Extractor extractor1,
+			     final Object object1,
+			     final Extractor extractor2,
+			     final Object object2) {
+			if ( extractor1.isNullValue( workingMemory,
+			              object1 ) ) {
+			return false;
+			}
+			long distStart = ((EventFactHandle) object1 ).getStartTimestamp() - ((EventFactHandle) object2 ).getStartTimestamp();
+			long distEnd = ((EventFactHandle) object2 ).getEndTimestamp() - ((EventFactHandle) object1 ).getEndTimestamp();
+			return this.getOperator().isNegated() ^ ( distStart >= this.startMinDev && distStart <= this.startMaxDev 
+					&& distEnd >= this.endMinDev && distEnd <= this.endMaxDev );
+		}
+
+        public String toString() {
+            return "during[" + startMinDev + ", " + startMaxDev + ", " + endMinDev + ", " + endMaxDev + "]";
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int PRIME = 31;
+            int result = super.hashCode();
+            result = PRIME * result + (int) (endMaxDev ^ (endMaxDev >>> 32));
+            result = PRIME * result + (int) (endMinDev ^ (endMinDev >>> 32));
+            result = PRIME * result + (int) (startMaxDev ^ (startMaxDev >>> 32));
+            result = PRIME * result + (int) (startMinDev ^ (startMinDev >>> 32));
+            return result;
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#equals(java.lang.Object)
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if ( this == obj ) return true;
+            if ( !super.equals( obj ) ) return false;
+            if ( getClass() != obj.getClass() ) return false;
+            final DuringEvaluator other = (DuringEvaluator) obj;
+            return endMaxDev == other.endMaxDev && endMinDev == other.endMinDev
+            	&& startMaxDev == other.startMaxDev && startMinDev == other.startMinDev;
+        }
+
+        /**
+         * This methods tries to parse the string of parameters to customize 
+         * the evaluator.
+         * 
+         * @param parameters
+         */
+        private void parseParameters(String parameters) {
+            if ( parameters == null || parameters.trim().length() == 0 ) {
+                // open bounded ranges
+                this.startMinDev = 1;
+                this.startMaxDev = Long.MAX_VALUE;
+                this.endMinDev = 1;
+                this.endMaxDev = Long.MAX_VALUE;
+                return;
+            }
+
+            try {
+                String[] ranges = parameters.split( "," );
+                if ( ranges.length == 1 ) {
+                    // deterministic point in time for deviation of the starts of the intervals 
+                    this.startMinDev = Long.parseLong( ranges[0] );
+                    this.startMaxDev = this.startMinDev;
+                    this.endMinDev = this.startMinDev;
+                    this.endMaxDev = this.startMinDev;
+                } else if ( ranges.length == 2 ) {
+                    // deterministic points in time for deviations of the starts and the ends of the intervals 
+                    this.startMinDev = Long.parseLong( ranges[0] );
+                    this.startMaxDev = this.startMinDev;
+                    this.endMinDev = Long.parseLong( ranges[1] );
+                    this.endMaxDev = this.endMinDev;
+                } else if ( ranges.length == 4 ) {
+                    // ranges for deviations of the starts and the ends of the intervals 
+                	this.startMinDev = Long.parseLong( ranges[0] );
+                    this.startMaxDev = Long.parseLong( ranges[1] );
+                    this.endMinDev = Long.parseLong( ranges[2] );
+                    this.endMaxDev = Long.parseLong( ranges[3] );
+                } else {
+                    throw new RuntimeDroolsException( "[During Evaluator]: Not possible to parse parameters: '" + parameters + "'" );
+                }
+            } catch ( NumberFormatException e ) {
+                throw new RuntimeDroolsException( "[During Evaluator]: Not possible to parse parameters: '" + parameters + "'",
+                                                  e );
+            }
+        }
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/EqualityEvaluatorsDefinition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/EqualityEvaluatorsDefinition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/EqualityEvaluatorsDefinition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,2110 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 6, 2007
+ */
+package org.drools.base.evaluators;
+
+import java.util.Date;
+
+import org.drools.base.BaseEvaluator;
+import org.drools.base.ShadowProxy;
+import org.drools.base.ValueType;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.VariableRestriction.BooleanVariableContextEntry;
+import org.drools.rule.VariableRestriction.CharVariableContextEntry;
+import org.drools.rule.VariableRestriction.DoubleVariableContextEntry;
+import org.drools.rule.VariableRestriction.LongVariableContextEntry;
+import org.drools.rule.VariableRestriction.ObjectVariableContextEntry;
+import org.drools.rule.VariableRestriction.VariableContextEntry;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldValue;
+import org.drools.util.DateUtils;
+
+/**
+ * This class defines the default built in equality
+ * evaluators == and !=
+ * 
+ * @author etirelli
+ */
+public class EqualityEvaluatorsDefinition implements EvaluatorDefinition {
+    
+    private static final String[] SUPPORTED_IDS = { Operator.EQUAL.getOperatorString(), Operator.NOT_EQUAL.getOperatorString() };
+    private EvaluatorCache evaluators = new EvaluatorCache() {
+        private static final long serialVersionUID = 4782368623L;
+        {
+            addEvaluator( ValueType.ARRAY_TYPE,         Operator.EQUAL,         ArrayEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.ARRAY_TYPE,         Operator.NOT_EQUAL,     ArrayNotEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.BIG_DECIMAL_TYPE,   Operator.EQUAL,         BigDecimalEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.BIG_DECIMAL_TYPE,   Operator.NOT_EQUAL,     BigDecimalNotEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.BIG_INTEGER_TYPE,   Operator.EQUAL,         BigIntegerEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.BIG_INTEGER_TYPE,   Operator.NOT_EQUAL,     BigIntegerNotEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.BOOLEAN_TYPE,       Operator.EQUAL,         BooleanEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.BOOLEAN_TYPE,       Operator.NOT_EQUAL,     BooleanNotEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PBOOLEAN_TYPE,      Operator.EQUAL,         BooleanEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PBOOLEAN_TYPE,      Operator.NOT_EQUAL,     BooleanNotEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.BYTE_TYPE,          Operator.EQUAL,         ByteEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.BYTE_TYPE,          Operator.NOT_EQUAL,     ByteNotEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PBYTE_TYPE,         Operator.EQUAL,         ByteEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PBYTE_TYPE,         Operator.NOT_EQUAL,     ByteNotEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.CHAR_TYPE,          Operator.EQUAL,         CharacterEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.CHAR_TYPE,          Operator.NOT_EQUAL,     CharacterNotEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PCHAR_TYPE,         Operator.EQUAL,         CharacterEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PCHAR_TYPE,         Operator.NOT_EQUAL,     CharacterNotEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.DATE_TYPE,          Operator.EQUAL,         DateEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.DATE_TYPE,          Operator.NOT_EQUAL,     DateNotEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.DOUBLE_TYPE,        Operator.EQUAL,         DoubleEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.DOUBLE_TYPE,        Operator.NOT_EQUAL,     DoubleNotEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PDOUBLE_TYPE,       Operator.EQUAL,         DoubleEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PDOUBLE_TYPE,       Operator.NOT_EQUAL,     DoubleNotEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.FACTTEMPLATE_TYPE,  Operator.EQUAL,         FactTemplateEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.FACTTEMPLATE_TYPE,  Operator.NOT_EQUAL,     FactTemplateNotEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.FLOAT_TYPE,         Operator.EQUAL,         FloatEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.FLOAT_TYPE,         Operator.NOT_EQUAL,     FloatNotEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PFLOAT_TYPE,        Operator.EQUAL,         FloatEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PFLOAT_TYPE,        Operator.NOT_EQUAL,     FloatNotEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.INTEGER_TYPE,       Operator.EQUAL,         IntegerEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.INTEGER_TYPE,       Operator.NOT_EQUAL,     IntegerNotEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PINTEGER_TYPE,      Operator.EQUAL,         IntegerEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PINTEGER_TYPE,      Operator.NOT_EQUAL,     IntegerNotEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.LONG_TYPE,          Operator.EQUAL,         LongEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.LONG_TYPE,          Operator.NOT_EQUAL,     LongNotEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PLONG_TYPE,         Operator.EQUAL,         LongEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PLONG_TYPE,         Operator.NOT_EQUAL,     LongNotEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.OBJECT_TYPE,        Operator.EQUAL,         ObjectEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.OBJECT_TYPE,        Operator.NOT_EQUAL,     ObjectNotEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.SHORT_TYPE,         Operator.EQUAL,         ShortEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.SHORT_TYPE,         Operator.NOT_EQUAL,     ShortNotEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PSHORT_TYPE,        Operator.EQUAL,         ShortEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.PSHORT_TYPE,        Operator.NOT_EQUAL,     ShortNotEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.STRING_TYPE,        Operator.EQUAL,         StringEqualEvaluator.INSTANCE );
+            addEvaluator( ValueType.STRING_TYPE,        Operator.NOT_EQUAL,     StringNotEqualEvaluator.INSTANCE );
+        }
+    };
+    
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator) {
+        return this.evaluators.getEvaluator( type,
+                                             operator );
+    }
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator,
+                                  String parameterText) {
+        return this.evaluators.getEvaluator( type,
+                                             operator );
+    }
+
+
+    public Evaluator getEvaluator(final ValueType type,
+                                  final String operatorId,
+                                  final boolean isNegated,
+                                  final String parameterText) {
+        return this.evaluators.getEvaluator( type, Operator.determineOperator( operatorId, isNegated ) );
+    }
+
+    public String[] getEvaluatorIds() {
+        return SUPPORTED_IDS;
+    }
+
+    public boolean isNegatable() {
+        return false;
+    }
+
+    public boolean operatesOnFactHandles() {
+        return false;
+    }
+
+    public boolean supportsType(ValueType type) {
+        return this.evaluators.supportsType( type );
+    }
+    
+    /*  *********************************************************
+     *           Evaluator Implementations
+     *  *********************************************************
+     */
+    
+    static class ArrayEqualEvaluator extends BaseEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ArrayEqualEvaluator();
+
+        private ArrayEqualEvaluator() {
+            super( ValueType.ARRAY_TYPE,
+                   Operator.EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            final Object value1 = extractor.getValue( workingMemory,
+                                                      object1 );
+            final Object value2 = object2.getValue();
+            if ( value1 == null ) {
+                return value2 == null;
+            }
+            return value1.equals( value2 );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context,
+                                           final Object left) {
+            final Object value = context.declaration.getExtractor().getValue( workingMemory,
+                                                                              left );
+            if ( value == null ) {
+                return ((ObjectVariableContextEntry) context).right == null;
+            }
+            return value.equals( ((ObjectVariableContextEntry) context).right );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context,
+                                          final Object right) {
+            final Object value = context.extractor.getValue( workingMemory,
+                                                             right );
+            if ( ((ObjectVariableContextEntry) context).left == null ) {
+                return value == null;
+            }
+            return ((ObjectVariableContextEntry) context).left.equals( value );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2,
+                                final Object object2) {
+            final Object value1 = extractor1.getValue( workingMemory,
+                                                       object1 );
+            final Object value2 = extractor2.getValue( workingMemory,
+                                                       object2 );
+            if ( value1 == null ) {
+                return value2 == null;
+            }
+            return value1.equals( value2 );
+        }
+
+        public String toString() {
+            return "Array ==";
+        }
+
+    }
+
+    static class ArrayNotEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ArrayNotEqualEvaluator();
+
+        private ArrayNotEqualEvaluator() {
+            super( ValueType.ARRAY_TYPE,
+                   Operator.NOT_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            final Object value1 = extractor.getValue( workingMemory,
+                                                      object1 );
+            final Object value2 = object2.getValue();
+            if ( value1 == null ) {
+                return value2 != null;
+            }
+            return !value1.equals( value2 );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context,
+                                           final Object left) {
+            final Object value = context.declaration.getExtractor().getValue( workingMemory,
+                                                                              left );
+            if ( value == null ) {
+                return ((ObjectVariableContextEntry) context).right != null;
+            }
+            return !value.equals( ((ObjectVariableContextEntry) context).right );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context,
+                                          final Object right) {
+            final Object value = context.extractor.getValue( workingMemory,
+                                                             right );
+            if ( ((ObjectVariableContextEntry) context).left == null ) {
+                return value != null;
+            }
+            return !((ObjectVariableContextEntry) context).left.equals( value );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2,
+                                final Object object2) {
+            final Object value1 = extractor1.getValue( workingMemory,
+                                                       object1 );
+            final Object value2 = extractor2.getValue( workingMemory,
+                                                       object2 );
+            if ( value1 == null ) {
+                return value2 != null;
+            }
+            return !value1.equals( value2 );
+        }
+
+        public String toString() {
+            return "Array !=";
+        }
+    }
+
+    static class BigDecimalEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new BigDecimalEqualEvaluator();
+
+        private BigDecimalEqualEvaluator() {
+            super( ValueType.BIG_DECIMAL_TYPE,
+                   Operator.EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            final Object value1 = extractor.getValue( workingMemory, object1 );
+            final Object value2 = object2.getValue();
+            if ( value1 == null ) {
+                return value2 == null;
+            }
+            return value1.equals( value2 );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            final Object value = context.declaration.getExtractor().getValue( workingMemory, left );
+            if ( value == null ) {
+                return ((ObjectVariableContextEntry) context).right == null;
+            }
+            return value.equals( ((ObjectVariableContextEntry) context).right );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            final Object value = context.extractor.getValue( workingMemory, right );
+            if ( ((ObjectVariableContextEntry) context).left == null ) {
+                return value == null;
+            }
+            return ((ObjectVariableContextEntry) context).left.equals( value );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            final Object value1 = extractor1.getValue( workingMemory, object1 );
+            final Object value2 = extractor2.getValue( workingMemory, object2 );
+            if ( value1 == null ) {
+                return value2 == null;
+            }
+            return value1.equals( value2 );
+        }
+
+        public String toString() {
+            return "BigDecimal ==";
+        }
+
+    }
+
+    static class BigDecimalNotEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new BigDecimalNotEqualEvaluator();
+
+        private BigDecimalNotEqualEvaluator() {
+            super( ValueType.BIG_DECIMAL_TYPE,
+                   Operator.NOT_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            final Object value1 = extractor.getValue( workingMemory, object1 );
+            final Object value2 = object2.getValue();
+            if ( value1 == null ) {
+                return value2 != null;
+            }
+            return !value1.equals( value2 );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            final Object value = context.declaration.getExtractor().getValue( workingMemory, left );
+            if ( value == null ) {
+                return ((ObjectVariableContextEntry) context).right != null;
+            }
+            return !value.equals( ((ObjectVariableContextEntry) context).right );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            final Object value = context.extractor.getValue( workingMemory, right );
+            if ( ((ObjectVariableContextEntry) context).left == null ) {
+                return value != null;
+            }
+            return !((ObjectVariableContextEntry) context).left.equals( value );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            final Object value1 = extractor1.getValue( workingMemory, object1 );
+            final Object value2 = extractor2.getValue( workingMemory, object2 );
+            if ( value1 == null ) {
+                return value2 != null;
+            }
+            return !value1.equals( value2 );
+        }
+
+        public String toString() {
+            return "BigDecimal !=";
+        }
+    }
+
+    static class BigIntegerEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new BigIntegerEqualEvaluator();
+
+        private BigIntegerEqualEvaluator() {
+            super( ValueType.BIG_INTEGER_TYPE,
+                   Operator.EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            final Object value1 = extractor.getValue( workingMemory, object1 );
+            final Object value2 = object2.getValue();
+            if ( value1 == null ) {
+                return value2 == null;
+            }
+            return value1.equals( value2 );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            final Object value = context.declaration.getExtractor().getValue( workingMemory, left );
+            if ( value == null ) {
+                return ((ObjectVariableContextEntry) context).right == null;
+            }
+            return value.equals( ((ObjectVariableContextEntry) context).right );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            final Object value = context.extractor.getValue( workingMemory, right );
+            if ( ((ObjectVariableContextEntry) context).left == null ) {
+                return value == null;
+            }
+            return ((ObjectVariableContextEntry) context).left.equals( value );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            final Object value1 = extractor1.getValue( workingMemory, object1 );
+            final Object value2 = extractor2.getValue( workingMemory, object2 );
+            if ( value1 == null ) {
+                return value2 == null;
+            }
+            return value1.equals( value2 );
+        }
+
+        public String toString() {
+            return "BigInteger ==";
+        }
+    }
+
+    static class BigIntegerNotEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new BigIntegerNotEqualEvaluator();
+
+        private BigIntegerNotEqualEvaluator() {
+            super( ValueType.BIG_INTEGER_TYPE,
+                   Operator.NOT_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            final Object value1 = extractor.getValue( workingMemory, object1 );
+            final Object value2 = object2.getValue();
+            if ( value1 == null ) {
+                return value2 != null;
+            }
+            return !value1.equals( value2 );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            final Object value = context.declaration.getExtractor().getValue( workingMemory, left );
+            if ( value == null ) {
+                return ((ObjectVariableContextEntry) context).right != null;
+            }
+            return !value.equals( ((ObjectVariableContextEntry) context).right );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            final Object value = context.extractor.getValue( workingMemory, right );
+            if ( ((ObjectVariableContextEntry) context).left == null ) {
+                return value != null;
+            }
+            return !((ObjectVariableContextEntry) context).left.equals( value );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            final Object value1 = extractor1.getValue( workingMemory, object1 );
+            final Object value2 = extractor2.getValue( workingMemory, object2 );
+            if ( value1 == null ) {
+                return value2 != null;
+            }
+            return !value1.equals( value2 );
+        }
+
+        public String toString() {
+            return "BigInteger !=";
+        }
+    }
+
+    static class BooleanEqualEvaluator extends BaseEvaluator {
+
+        private static final long      serialVersionUID = 400L;
+        private final static Evaluator INSTANCE         = new BooleanEqualEvaluator();
+
+        private BooleanEqualEvaluator() {
+            super( ValueType.PBOOLEAN_TYPE,
+                   Operator.EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if ( extractor.isNullValue( workingMemory, object1 ) ) {
+                return object2.isNull();
+            } else if ( object2.isNull() ) {
+                return false;
+            }
+            
+            return extractor.getBooleanValue( workingMemory, object1 ) == object2.getBooleanValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if ( context.declaration.getExtractor().isNullValue( workingMemory, left ) ) {
+                return context.isRightNull();
+            } else if ( context.isRightNull() ) {
+                return false;
+            }
+            
+            return context.declaration.getExtractor().getBooleanValue( workingMemory, left ) == ((BooleanVariableContextEntry) context).right;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object object2) {
+            if ( context.extractor.isNullValue( workingMemory, object2 )) {
+                return context.isLeftNull();
+            } else if ( context.isLeftNull() ) {
+                return false;
+            }
+            
+            return context.extractor.getBooleanValue( workingMemory, object2 ) == ((BooleanVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if (extractor1.isNullValue( workingMemory, object1 )) {
+                return extractor2.isNullValue( workingMemory, object2 );
+            } else if (extractor2.isNullValue( workingMemory, object2 )) {
+                return false;
+            }
+            
+            return extractor1.getBooleanValue( workingMemory, object1 ) == extractor2.getBooleanValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Boolean ==";
+        }
+
+    }
+
+    static class BooleanNotEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new BooleanNotEqualEvaluator();
+
+        private BooleanNotEqualEvaluator() {
+            super( ValueType.PBOOLEAN_TYPE,
+                   Operator.NOT_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if ( extractor.isNullValue( workingMemory, object1 ) ) {
+                return !object2.isNull();
+            } else if ( object2.isNull() ) {
+                return true;
+            }
+            
+            return extractor.getBooleanValue( workingMemory, object1 ) != object2.getBooleanValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if ( context.declaration.getExtractor().isNullValue( workingMemory, left ) ) {
+                return !context.isRightNull();
+            } else if ( context.isRightNull() ) {
+                return true;
+            }
+            return context.declaration.getExtractor().getBooleanValue( workingMemory, left ) != ((BooleanVariableContextEntry) context).right;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object object2) {
+            if ( context.extractor.isNullValue( workingMemory, object2 )) {
+                return !context.isLeftNull();
+            } else if ( context.isLeftNull() ) {
+                return true;
+            }
+            
+            return context.extractor.getBooleanValue( workingMemory, object2 ) != ((BooleanVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if (extractor1.isNullValue( workingMemory, object1 )) {
+                return !extractor2.isNullValue( workingMemory, object2 );
+            } else if (extractor2.isNullValue( workingMemory, object2 )) {
+                return true;
+            }
+            
+            return extractor1.getBooleanValue( workingMemory, object1 ) != extractor1.getBooleanValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Boolean !=";
+        }
+    }
+
+    static class ByteEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ByteEqualEvaluator();
+
+        private ByteEqualEvaluator() {
+            super( ValueType.PBYTE_TYPE,
+                   Operator.EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if ( extractor.isNullValue( workingMemory, object1 ) ) {
+                return object2.isNull();
+            } else if ( object2.isNull() ) {
+                return false;
+            }
+            
+            return extractor.getByteValue( workingMemory, object1 ) == object2.getByteValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if ( context.declaration.getExtractor().isNullValue( workingMemory, left ) ) {
+                return context.isRightNull();
+            } else if ( context.isRightNull() ) {
+                return false;
+            }
+            
+            return context.declaration.getExtractor().getByteValue( workingMemory, left ) == ((LongVariableContextEntry) context).right;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if ( context.extractor.isNullValue( workingMemory, right )) {
+                return context.isLeftNull();
+            } else if ( context.isLeftNull() ) {
+                return false;
+            }
+            
+            return ((LongVariableContextEntry) context).left == context.extractor.getByteValue( workingMemory, right );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if (extractor1.isNullValue( workingMemory, object1 )) {
+                return extractor2.isNullValue( workingMemory, object2 );
+            } else if (extractor2.isNullValue( workingMemory, object2 )) {
+                return false;
+            }
+            
+            return extractor1.getByteValue( workingMemory, object1 ) == extractor2.getByteValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Byte ==";
+        }
+
+    }
+
+    static class ByteNotEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ByteNotEqualEvaluator();
+
+        private ByteNotEqualEvaluator() {
+            super( ValueType.PBYTE_TYPE,
+                   Operator.NOT_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if ( extractor.isNullValue( workingMemory, object1 ) ) {
+                return !object2.isNull();
+            } else if ( object2.isNull() ) {
+                return true;
+            }
+            
+            return extractor.getByteValue( workingMemory, object1 ) != object2.getByteValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if ( context.declaration.getExtractor().isNullValue( workingMemory, left ) ) {
+                return !context.isRightNull();
+            } else if ( context.isRightNull() ) {
+                return true;
+            }
+            
+            return context.declaration.getExtractor().getByteValue( workingMemory, left ) != ((LongVariableContextEntry) context).right;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object object2) {
+            if ( context.extractor.isNullValue( workingMemory, object2 ) ) {
+                return !context.isLeftNull();
+            } else if ( context.isLeftNull() ) {
+                return true;
+            }
+            
+            return ((LongVariableContextEntry) context).left != context.extractor.getByteValue( workingMemory, object2 );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if (extractor1.isNullValue( workingMemory, object1 )) {
+                return !extractor2.isNullValue( workingMemory, object2 );
+            } else if (extractor2.isNullValue( workingMemory, object2 )) {
+                return true;
+            }
+            
+            return extractor1.getByteValue( workingMemory, object1 ) != extractor2.getByteValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Byte !=";
+        }
+    }
+
+    static class CharacterEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new CharacterEqualEvaluator();
+
+        private CharacterEqualEvaluator() {
+            super( ValueType.PCHAR_TYPE,
+                   Operator.EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if ( extractor.isNullValue( workingMemory, object1 ) ) {
+                return object2.isNull();
+            } else if ( object2.isNull() ) {
+                return false;
+            }
+            
+            return extractor.getCharValue( workingMemory, object1 ) == object2.getCharValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if ( context.declaration.getExtractor().isNullValue( workingMemory, left ) ) {
+                return context.isRightNull();
+            } else if ( context.isRightNull() ) {
+                return false;
+            }
+            
+            return context.declaration.getExtractor().getCharValue( workingMemory, left ) == ((CharVariableContextEntry) context).right;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if ( context.extractor.isNullValue( workingMemory, right )) {
+                return context.isLeftNull();
+            } else if ( context.isLeftNull() ) {
+                return false;
+            }
+            
+            return ((CharVariableContextEntry) context).left == context.extractor.getCharValue( workingMemory, right );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if (extractor1.isNullValue( workingMemory, object1 )) {
+                return extractor2.isNullValue( workingMemory, object2 );
+            } else if (extractor2.isNullValue( workingMemory, object2 )) {
+                return false;
+            }
+            
+            return extractor1.getCharValue( workingMemory, object1 ) == extractor2.getCharValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Character ==";
+        }
+    }
+
+    static class CharacterNotEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new CharacterNotEqualEvaluator();
+
+        private CharacterNotEqualEvaluator() {
+            super( ValueType.PCHAR_TYPE,
+                   Operator.NOT_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if ( extractor.isNullValue( workingMemory, object1 ) ) {
+                return !object2.isNull();
+            } else if ( object2.isNull() ) {
+                return true;
+            }
+            
+            return extractor.getCharValue( workingMemory, object1 ) != object2.getCharValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if ( context.declaration.getExtractor().isNullValue( workingMemory, left ) ) {
+                return !context.isRightNull();
+            } else if ( context.isRightNull() ) {
+                return true;
+            }
+            
+            return context.declaration.getExtractor().getCharValue( workingMemory, left ) != ((CharVariableContextEntry) context).right;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if ( context.extractor.isNullValue( workingMemory, right ) ) {
+                return !context.isLeftNull();
+            } else if ( context.isLeftNull() ) {
+                return true;
+            }
+            
+            return ((CharVariableContextEntry) context).left != context.extractor.getCharValue( workingMemory, right );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if (extractor1.isNullValue( workingMemory, object1 )) {
+                return !extractor2.isNullValue( workingMemory, object2 );
+            } else if (extractor2.isNullValue( workingMemory, object2 )) {
+                return true;
+            }
+            
+            return extractor1.getCharValue( workingMemory, object1 ) != extractor2.getCharValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Character !=";
+        }
+    }
+
+    static class DateEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new DateEqualEvaluator();
+
+        private DateEqualEvaluator() {
+            super( ValueType.DATE_TYPE,
+                   Operator.EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            final Date value1 = (Date) extractor.getValue( workingMemory, object1 );
+            final Object value2 = object2.getValue();
+            if ( value1 == null ) {
+                return value2 == null;
+            }
+            if ( value2 == null ) {
+                return false;
+            }
+            return value1.compareTo( DateUtils.getRightDate( value2 ) ) == 0;
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            final Date value1 = (Date) context.declaration.getExtractor().getValue( workingMemory, left );
+            final Object value2 = ((ObjectVariableContextEntry) context).right;
+            if ( value1 == null ) {
+                return value2 == null;
+            }
+            if ( value2 == null ) {
+                return false;
+            }
+            return value1.compareTo( DateUtils.getRightDate( value2 ) ) == 0;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            final Date value1 = (Date) ((ObjectVariableContextEntry) context).left;
+            final Object value2 = context.extractor.getValue( workingMemory, right );
+            if ( value1 == null ) {
+                return value2 == null;
+            }
+            if ( value2 == null ) {
+                return false;
+            }
+            return value1.compareTo( DateUtils.getRightDate( value2 ) ) == 0;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            final Date value1 = (Date) extractor1.getValue( workingMemory, object1 );
+            final Date value2 = (Date) extractor2.getValue( workingMemory, object2 );
+            if ( value1 == null ) {
+                return value2 == null;
+            }
+            if ( value2 == null ) {
+                return false;
+            }
+            return value1.compareTo( value2 ) == 0;
+        }
+
+        public String toString() {
+            return "Date ==";
+        }
+
+    }
+
+    static class DateNotEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new DateNotEqualEvaluator();
+
+        private DateNotEqualEvaluator() {
+            super( ValueType.DATE_TYPE,
+                   Operator.NOT_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            final Date value1 = (Date) extractor.getValue( workingMemory, object1 );
+            final Object value2 = object2.getValue();
+            if ( value1 == null ) {
+                return value2 != null;
+            }
+            if ( value2 == null ) {
+                return true;
+            }
+            return value1.compareTo( DateUtils.getRightDate( value2 ) ) != 0;
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            final Date value1 = (Date) context.declaration.getExtractor().getValue( workingMemory, left );
+            final Object value2 = ((ObjectVariableContextEntry) context).right;
+            if ( value1 == null ) {
+                return value2 != null;
+            }
+            if ( value2 == null ) {
+                return true;
+            }
+            return value1.compareTo( DateUtils.getRightDate( value2 ) ) != 0;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            final Date value1 = (Date) ((ObjectVariableContextEntry) context).left;
+            final Object value2 = context.extractor.getValue( workingMemory, right );
+            if ( value1 == null ) {
+                return value2 != null;
+            }
+            if ( value2 == null ) {
+                return true;
+            }
+            return value1.compareTo( DateUtils.getRightDate( value2 ) ) != 0;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            final Date value1 = (Date) extractor1.getValue( workingMemory, object1 );
+            final Date value2 = (Date) extractor2.getValue( workingMemory, object2 );
+            if ( value1 == null ) {
+                return value2 != null;
+            }
+            if ( value2 == null ) {
+                return true;
+            }
+            return value1.compareTo( value2 ) != 0;
+        }
+
+        public String toString() {
+            return "Date !=";
+        }
+    }
+
+    static class DoubleEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new DoubleEqualEvaluator();
+
+        private DoubleEqualEvaluator() {
+            super( ValueType.PDOUBLE_TYPE,
+                   Operator.EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if ( extractor.isNullValue( workingMemory, object1 ) ) {
+                return object2.isNull();
+            } else if ( object2.isNull() ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor.getDoubleValue( workingMemory, object1 ) == object2.getDoubleValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if ( context.declaration.getExtractor().isNullValue( workingMemory, left ) ) {
+                return context.isRightNull();
+            } else if ( context.isRightNull() ) {
+                return false;
+            }
+            // TODO: we are not handling delta right now... maybe we should
+            return context.declaration.getExtractor().getDoubleValue( workingMemory, left ) == ((DoubleVariableContextEntry) context).right;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if ( context.extractor.isNullValue( workingMemory, right )) {
+                return context.isLeftNull();
+            } else if ( context.isLeftNull() ) {
+                return false;
+            }
+            
+            // TODO: we are not handling delta right now... maybe we should
+            return ((DoubleVariableContextEntry) context).left == context.extractor.getDoubleValue( workingMemory, right );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if (extractor1.isNullValue( workingMemory, object1 )) {
+                return extractor2.isNullValue( workingMemory, object2 );
+            } else if (extractor2.isNullValue( workingMemory, object2 )) {
+                return false;
+            }
+            
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor1.getDoubleValue( workingMemory, object1 ) == extractor2.getDoubleValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Double ==";
+        }
+    }
+
+    static class DoubleNotEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new DoubleNotEqualEvaluator();
+
+        private DoubleNotEqualEvaluator() {
+            super( ValueType.PDOUBLE_TYPE,
+                   Operator.NOT_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if ( extractor.isNullValue( workingMemory, object1 ) ) {
+                return !object2.isNull();
+            } else if ( object2.isNull() ) {
+                return true;
+            }
+            
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor.getDoubleValue( workingMemory, object1 ) != object2.getDoubleValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if ( context.declaration.getExtractor().isNullValue( workingMemory, left ) ) {
+                return !context.isRightNull();
+            } else if ( context.isRightNull() ) {
+                return true;
+            }
+            
+            // TODO: we are not handling delta right now... maybe we should
+            return context.declaration.getExtractor().getDoubleValue( workingMemory, left ) != ((DoubleVariableContextEntry) context).right;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if ( context.extractor.isNullValue( workingMemory, right )) {
+                return !context.isLeftNull();
+            } else if ( context.isLeftNull() ) {
+                return true;
+            }
+            
+            // TODO: we are not handling delta right now... maybe we should
+            return ((DoubleVariableContextEntry) context).left != context.extractor.getDoubleValue( workingMemory, right );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if (extractor1.isNullValue( workingMemory, object1 )) {
+                return !extractor2.isNullValue( workingMemory, object2 );
+            } else if (extractor2.isNullValue( workingMemory, object2 )) {
+                return true;
+            }
+            
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor1.getDoubleValue( workingMemory, object1 ) != extractor2.getDoubleValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Double !=";
+        }
+    }
+
+    static class FactTemplateEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new FactTemplateEqualEvaluator();
+
+        private FactTemplateEqualEvaluator() {
+            super( ValueType.FACTTEMPLATE_TYPE,
+                   Operator.EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            final Object value1 = extractor.getValue( workingMemory, object1 );
+            final Object value2 = object2.getValue();
+            if ( value1 == null ) {
+                return value2 == null;
+            }
+            return value1.equals( value2 );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            final Object value = context.declaration.getExtractor().getValue( workingMemory, left );
+            if ( value == null ) {
+                return ((ObjectVariableContextEntry) context).right == null;
+            }
+            return value.equals( ((ObjectVariableContextEntry) context).right );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            final Object value = context.extractor.getValue( workingMemory, right );
+            if ( ((ObjectVariableContextEntry) context).left == null ) {
+                return value == null;
+            }
+            return ((ObjectVariableContextEntry) context).left.equals( value );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            final Object value1 = extractor1.getValue( workingMemory, object1 );
+            final Object value2 = extractor2.getValue( workingMemory, object2 );
+            if ( value1 == null ) {
+                return value2 == null;
+            }
+            return value1.equals( value2 );
+        }
+
+        public String toString() {
+            return "FactTemplate ==";
+        }
+
+    }
+
+    static class FactTemplateNotEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new FactTemplateNotEqualEvaluator();
+
+        private FactTemplateNotEqualEvaluator() {
+            super( ValueType.FACTTEMPLATE_TYPE,
+                   Operator.NOT_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            final Object value1 = extractor.getValue( workingMemory, object1 );
+            final Object value2 = object2.getValue();
+            if ( value1 == null ) {
+                return value2 != null;
+            }
+            return !value1.equals( value2 );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            final Object value = context.declaration.getExtractor().getValue( workingMemory, left );
+            if ( value == null ) {
+                return ((ObjectVariableContextEntry) context).right != null;
+            }
+            return !value.equals( ((ObjectVariableContextEntry) context).right );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            final Object value = context.extractor.getValue( workingMemory, right );
+            if ( ((ObjectVariableContextEntry) context).left == null ) {
+                return value != null;
+            }
+            return !((ObjectVariableContextEntry) context).left.equals( value );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            final Object value1 = extractor1.getValue( workingMemory, object1 );
+            final Object value2 = extractor2.getValue( workingMemory, object2 );
+            if ( value1 == null ) {
+                return value2 != null;
+            }
+            return !value1.equals( value2 );
+        }
+
+        public String toString() {
+            return "FactTemplate !=";
+        }
+    }
+    
+    static class FloatEqualEvaluator extends BaseEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new FloatEqualEvaluator();
+
+        private FloatEqualEvaluator() {
+            super( ValueType.PFLOAT_TYPE,
+                   Operator.EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if ( extractor.isNullValue( workingMemory, object1 ) ) {
+                return object2.isNull();
+            } else if ( object2.isNull() ) {
+                return false;
+            }
+            
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor.getFloatValue( workingMemory, object1 ) == object2.getFloatValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if ( context.declaration.getExtractor().isNullValue( workingMemory, left ) ) {
+                return context.isRightNull();
+            } else if ( context.isRightNull() ) {
+                return false;
+            }
+            
+            // TODO: we are not handling delta right now... maybe we should
+            return context.declaration.getExtractor().getFloatValue( workingMemory, left ) == ((DoubleVariableContextEntry) context).right;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if ( context.extractor.isNullValue( workingMemory, right )) {
+                return context.isLeftNull();
+            } else if ( context.isLeftNull() ) {
+                return false;
+            }
+            
+            // TODO: we are not handling delta right now... maybe we should
+            return ((DoubleVariableContextEntry) context).left == context.extractor.getFloatValue( workingMemory, right );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if (extractor1.isNullValue( workingMemory, object1 )) {
+                return extractor2.isNullValue( workingMemory, object2 );
+            } else if (extractor2.isNullValue( workingMemory, object2 )) {
+                return false;
+            }
+            
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor1.getFloatValue( workingMemory, object1 ) == extractor2.getFloatValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Float ==";
+        }
+    }
+
+    static class FloatNotEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new FloatNotEqualEvaluator();
+
+        private FloatNotEqualEvaluator() {
+            super( ValueType.PFLOAT_TYPE,
+                   Operator.NOT_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if ( extractor.isNullValue( workingMemory, object1 ) ) {
+                return !object2.isNull();
+            } else if ( object2.isNull() ) {
+                return true;
+            }
+            
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor.getFloatValue( workingMemory, object1 ) != object2.getFloatValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if ( context.declaration.getExtractor().isNullValue( workingMemory, left ) ) {
+                return !context.isRightNull();
+            } else if ( context.isRightNull() ) {
+                return true;
+            }
+            
+            // TODO: we are not handling delta right now... maybe we should
+            return context.declaration.getExtractor().getFloatValue( workingMemory, left ) != ((DoubleVariableContextEntry) context).right;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if ( context.extractor.isNullValue( workingMemory, right ) ) {
+                return !context.isLeftNull();
+            } else if ( context.isLeftNull() ) {
+                return true;
+            }
+            
+            // TODO: we are not handling delta right now... maybe we should
+            return ((DoubleVariableContextEntry) context).left != context.extractor.getFloatValue( workingMemory, right );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if (extractor1.isNullValue( workingMemory, object1 )) {
+                return !extractor2.isNullValue( workingMemory, object2 );
+            } else if (extractor2.isNullValue( workingMemory, object2 )) {
+                return true;
+            }
+            
+            // TODO: we are not handling delta right now... maybe we should
+            return extractor1.getFloatValue( workingMemory, object1 ) != extractor2.getFloatValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Float !=";
+        }
+    }
+
+    static class IntegerEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new IntegerEqualEvaluator();
+
+        private IntegerEqualEvaluator() {
+            super( ValueType.PINTEGER_TYPE,
+                   Operator.EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if ( extractor.isNullValue( workingMemory, object1 ) ) {
+                return object2.isNull();
+            } else if ( object2.isNull() ) {
+                return false;
+            }
+            
+            return extractor.getIntValue( workingMemory, object1 ) == object2.getIntValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if ( context.declaration.getExtractor().isNullValue( workingMemory, left ) ) {
+                return context.isRightNull();
+            } else if ( context.isRightNull() ) {
+                return false;
+            }
+            
+            return context.declaration.getExtractor().getIntValue( workingMemory, left ) == ((LongVariableContextEntry) context).right; 
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object object2) {
+            if ( context.extractor.isNullValue( workingMemory, object2 )) {
+                return context.isLeftNull();
+            } else if ( context.isLeftNull() ) {
+                return false;
+            }
+            
+            return context.extractor.getIntValue( workingMemory, object2 ) == ((LongVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {            
+            if (extractor1.isNullValue( workingMemory, object1 )) {
+                return extractor2.isNullValue( workingMemory, object2 );
+            } else if (extractor2.isNullValue( workingMemory, object2 )) {
+                return false;
+            }
+            
+            return extractor1.getIntValue( workingMemory, object1 ) == extractor2.getIntValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Integer ==";
+        }
+
+    }
+
+    static class IntegerNotEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new IntegerNotEqualEvaluator();
+
+        private IntegerNotEqualEvaluator() {
+            super( ValueType.PINTEGER_TYPE,
+                   Operator.NOT_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {                     
+            if ( extractor.isNullValue( workingMemory, object1 ) ) {
+                return !object2.isNull();
+            } else if ( object2.isNull() ) {
+                return true;
+            }
+            
+            return extractor.getIntValue( workingMemory, object1 ) != object2.getIntValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if ( context.declaration.getExtractor().isNullValue( workingMemory, left ) ) {
+                return !context.isRightNull();
+            } else if ( context.isRightNull() ) {
+                return true;
+            }
+            
+            return context.declaration.getExtractor().getIntValue( workingMemory, left ) != ((LongVariableContextEntry) context).right;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object object2) {
+            if ( context.extractor.isNullValue( workingMemory, object2 ) ) {
+                return !context.isLeftNull();
+            } else if ( context.isLeftNull() ) {
+                return true;
+            }
+            
+            return context.extractor.getIntValue( workingMemory, object2 ) != ((LongVariableContextEntry) context).left;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if (extractor1.isNullValue( workingMemory, object1 )) {
+                return !extractor2.isNullValue( workingMemory, object2 );
+            } else if (extractor2.isNullValue( workingMemory, object2 )) {
+                return true;
+            }
+            
+            return extractor1.getIntValue( workingMemory, object1 ) != extractor2.getIntValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Integer !=";
+        }
+    }
+
+    static class LongEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new LongEqualEvaluator();
+
+        private LongEqualEvaluator() {
+            super( ValueType.PLONG_TYPE,
+                   Operator.EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if ( extractor.isNullValue( workingMemory, object1 ) ) {
+                return object2.isNull();
+            } else if ( object2.isNull() ) {
+                return false;
+            }
+            
+            return extractor.getLongValue( workingMemory, object1 ) == object2.getLongValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if ( context.declaration.getExtractor().isNullValue( workingMemory, left ) ) {
+                return context.isRightNull();
+            } else if ( context.isRightNull() ) {
+                return false;
+            }
+            
+            return context.declaration.getExtractor().getLongValue( workingMemory, left ) == ((LongVariableContextEntry) context).right;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if ( context.extractor.isNullValue( workingMemory, right )) {
+                return context.isLeftNull();
+            } else if ( context.isLeftNull() ) {
+                return false;
+            }
+            
+            return ((LongVariableContextEntry) context).left == context.extractor.getLongValue( workingMemory, right );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if (extractor1.isNullValue( workingMemory, object1 )) {
+                return extractor2.isNullValue( workingMemory, object2 );
+            } else if (extractor2.isNullValue( workingMemory, object2 )) {
+                return false;
+            }
+            
+            return extractor1.getLongValue( workingMemory, object1 ) == extractor2.getLongValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Long ==";
+        }
+    }
+
+    static class LongNotEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new LongNotEqualEvaluator();
+
+        private LongNotEqualEvaluator() {
+            super( ValueType.PLONG_TYPE,
+                   Operator.NOT_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if ( extractor.isNullValue( workingMemory, object1 ) ) {
+                return !object2.isNull();
+            } else if ( object2.isNull() ) {
+                return true;
+            }
+            
+            return extractor.getLongValue( workingMemory, object1 ) != object2.getLongValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if ( context.declaration.getExtractor().isNullValue( workingMemory, left ) ) {
+                return !context.isRightNull();
+            } else if ( context.isRightNull() ) {
+                return true;
+            }
+            
+            return context.declaration.getExtractor().getLongValue( workingMemory, left ) != ((LongVariableContextEntry) context).right;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if ( context.extractor.isNullValue( workingMemory, right ) ) {
+                return !context.isLeftNull();
+            } else if ( context.isLeftNull() ) {
+                return true;
+            }
+            
+            return ((LongVariableContextEntry) context).left != context.extractor.getLongValue( workingMemory, right );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if (extractor1.isNullValue( workingMemory, object1 )) {
+                return !extractor2.isNullValue( workingMemory, object2 );
+            } else if (extractor2.isNullValue( workingMemory, object2 )) {
+                return true;
+            }
+            
+            return extractor1.getLongValue( workingMemory, object1 ) != extractor2.getLongValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Long !=";
+        }
+    }
+
+    static class ObjectEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ObjectEqualEvaluator();
+        private static final ObjectEqualsComparator comparator = new ObjectEqualsComparator();   
+        
+        private ObjectEqualEvaluator() {
+            super( ValueType.OBJECT_TYPE,
+                   Operator.EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            final Object value1 = extractor.getValue( workingMemory, object1 );
+            final Object value2 = object2.getValue();
+            if ( value1 == null ) {
+                return value2 == null;
+            }
+            if( value2 != null && value2 instanceof ShadowProxy ) {
+                return comparator.equals( value2, value1 );
+            }
+            return comparator.equals( value1, value2 );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            final Object value = context.declaration.getExtractor().getValue( workingMemory, left );
+            if ( value == null ) {
+                return ((ObjectVariableContextEntry) context).right == null;
+            }
+            if( ((ObjectVariableContextEntry) context).right != null && ((ObjectVariableContextEntry) context).right instanceof ShadowProxy ) {
+                return comparator.equals( ((ObjectVariableContextEntry) context).right,  value );
+            }
+            return comparator.equals( value, ((ObjectVariableContextEntry) context).right );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            final Object value = context.extractor.getValue( workingMemory, right );
+            if ( ((ObjectVariableContextEntry) context).left == null ) {
+                return value == null;
+            }
+            if( value != null && value instanceof ShadowProxy ) {
+                return comparator.equals( value, ((ObjectVariableContextEntry) context).left );
+            }
+            return comparator.equals( ((ObjectVariableContextEntry) context).left, value );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            final Object value1 = extractor1.getValue( workingMemory, object1 );
+            final Object value2 = extractor2.getValue( workingMemory, object2 );
+            if ( value1 == null ) {
+                return value2 == null;
+            }
+            if( value2 != null && value2 instanceof ShadowProxy ) {
+                return comparator.equals( value2, value1 );
+            }
+            return comparator.equals( value1, value2 );
+        }
+
+        public String toString() {
+            return "Object ==";
+        }
+
+    }
+
+    static class ObjectNotEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ObjectNotEqualEvaluator();
+        private static final ObjectEqualsComparator comparator = new ObjectEqualsComparator();           
+
+        private ObjectNotEqualEvaluator() {
+            super( ValueType.OBJECT_TYPE,
+                   Operator.NOT_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            final Object value1 = extractor.getValue( workingMemory, object1 );
+            final Object value2 = object2.getValue();
+            if ( value1 == null ) {
+                return value2 != null;
+            }
+            if( value2 != null && value2 instanceof ShadowProxy ) {
+                return !comparator.equals( value2, value1 );
+            }
+            return !comparator.equals( value1, value2 );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            final Object value = context.declaration.getExtractor().getValue( workingMemory, left );
+            if ( value == null ) {
+                return ((ObjectVariableContextEntry) context).right != null;
+            }
+            if( ((ObjectVariableContextEntry) context).right != null && ((ObjectVariableContextEntry) context).right instanceof ShadowProxy ) {
+                return !comparator.equals( ((ObjectVariableContextEntry) context).right, value );
+            }
+            return !comparator.equals( value, ((ObjectVariableContextEntry) context).right );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            final Object value = context.extractor.getValue( workingMemory, right );
+            if ( ((ObjectVariableContextEntry) context).left == null ) {
+                return value != null;
+            }
+            if( value != null && value instanceof ShadowProxy ) {
+                return !comparator.equals( value, ((ObjectVariableContextEntry) context).left );
+            }
+            return !comparator.equals( ((ObjectVariableContextEntry) context).left, value );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            final Object value1 = extractor1.getValue( workingMemory, object1 );
+            final Object value2 = extractor2.getValue( workingMemory, object2 );
+            if ( value1 == null ) {
+                return value2 != null;
+            }
+            if( value2 != null && value2 instanceof ShadowProxy ) {
+                return !comparator.equals( value2, value1 );
+            }
+            return !comparator.equals( value1, value2 );
+        }
+
+        public String toString() {
+            return "Object !=";
+        }
+    }
+
+    static class ShortEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long      serialVersionUID = 400L;
+        private static final Evaluator INSTANCE         = new ShortEqualEvaluator();
+
+        private ShortEqualEvaluator() {
+            super( ValueType.PSHORT_TYPE,
+                   Operator.EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if ( extractor.isNullValue( workingMemory, object1 ) ) {
+                return object2.isNull();
+            } else if ( object2.isNull() ) {
+                return false;
+            }
+            
+            return extractor.getShortValue( workingMemory, object1 ) == object2.getShortValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if ( context.declaration.getExtractor().isNullValue( workingMemory, left ) ) {
+                return context.isRightNull();
+            } else if ( context.isRightNull() ) {
+                return false;
+            }
+            
+            return context.declaration.getExtractor().getShortValue( workingMemory, left ) == ((LongVariableContextEntry) context).right;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if ( context.extractor.isNullValue( workingMemory, right )) {
+                return context.isLeftNull();
+            } else if ( context.isLeftNull() ) {
+                return false;
+            }
+            
+            return ((LongVariableContextEntry) context).left == context.extractor.getShortValue( workingMemory, right );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if (extractor1.isNullValue( workingMemory, object1 )) {
+                return extractor2.isNullValue( workingMemory, object2 );
+            } else if (extractor2.isNullValue( workingMemory, object2 )) {
+                return false;
+            }
+            
+            return extractor1.getShortValue( workingMemory, object1 ) == extractor2.getShortValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Short ==";
+        }
+    }
+
+    static class ShortNotEqualEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long      serialVersionUID = 400L;
+        private static final Evaluator INSTANCE         = new ShortNotEqualEvaluator();
+
+        private ShortNotEqualEvaluator() {
+            super( ValueType.PSHORT_TYPE,
+                   Operator.NOT_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            if ( extractor.isNullValue( workingMemory, object1 ) ) {
+                return !object2.isNull();
+            } else if ( object2.isNull() ) {
+                return true;
+            }
+            
+            return extractor.getShortValue( workingMemory, object1 ) != object2.getShortValue();
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            if ( context.declaration.getExtractor().isNullValue( workingMemory, left ) ) {
+                return !context.isRightNull();
+            } else if ( context.isRightNull() ) {
+                return true;
+            }
+            
+            return context.declaration.getExtractor().getShortValue( workingMemory, left ) != ((LongVariableContextEntry) context).right;
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            if ( context.extractor.isNullValue( workingMemory, right ) ) {
+                return !context.isLeftNull();
+            } else if ( context.isLeftNull() ) {
+                return true;
+            }
+            
+            return ((LongVariableContextEntry) context).left != context.extractor.getShortValue( workingMemory, right );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            if (extractor1.isNullValue( workingMemory, object1 )) {
+                return !extractor2.isNullValue( workingMemory, object2 );
+            } else if (extractor2.isNullValue( workingMemory, object2 )) {
+                return true;
+            }
+            
+            return extractor1.getShortValue( workingMemory, object1 ) != extractor2.getShortValue( workingMemory, object2 );
+        }
+
+        public String toString() {
+            return "Short !=";
+        }
+    }
+
+    static class StringEqualEvaluator extends BaseEvaluator {
+        /**
+         *
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new StringEqualEvaluator();
+
+        private StringEqualEvaluator() {
+            super( ValueType.STRING_TYPE,
+                   Operator.EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            final Object value1 = extractor.getValue( workingMemory, object1 );
+            final Object value2 = object2.getValue();
+            if ( value1 == null ) {
+                return value2 == null;
+            }
+            return value1.equals( value2 );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            final Object value = context.declaration.getExtractor().getValue( workingMemory, left );
+            if ( value == null ) {
+                return ((ObjectVariableContextEntry) context).right == null;
+            }
+            return value.equals( ((ObjectVariableContextEntry) context).right );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            final Object value = context.extractor.getValue( workingMemory, right );
+            if ( ((ObjectVariableContextEntry) context).left == null ) {
+                return value == null;
+            }
+            return ((ObjectVariableContextEntry) context).left.equals( value );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            final Object value1 = extractor1.getValue( workingMemory, object1 );
+            final Object value2 = extractor2.getValue( workingMemory, object2 );
+            if ( value1 == null ) {
+                return value2 == null;
+            }
+            return value1.equals( value2 );
+        }
+
+        public String toString() {
+            return "String ==";
+        }
+
+    }
+
+    static class StringNotEqualEvaluator extends BaseEvaluator {
+        /**
+         *
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new StringNotEqualEvaluator();
+
+        private StringNotEqualEvaluator() {
+            super( ValueType.STRING_TYPE,
+                   Operator.NOT_EQUAL );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            final Object value1 = extractor.getValue( workingMemory, object1 );
+            final Object value2 = object2.getValue();
+            if ( value1 == null ) {
+                return value2 != null;
+            }
+            return !value1.equals( value2 );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            final Object value = context.declaration.getExtractor().getValue( workingMemory, left );
+            if ( value == null ) {
+                return ((ObjectVariableContextEntry) context).right != null;
+            }
+            return !value.equals( ((ObjectVariableContextEntry) context).right );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            final Object value = context.extractor.getValue( workingMemory, right );
+            if ( ((ObjectVariableContextEntry) context).left == null ) {
+                return value != null;
+            }
+            return !((ObjectVariableContextEntry) context).left.equals( value );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            final Object value1 = extractor1.getValue( workingMemory, object1 );
+            final Object value2 = extractor2.getValue( workingMemory, object2 );
+            if ( value1 == null ) {
+                return value2 != null;
+            }
+            return !value1.equals( value2 );
+        }
+
+        public String toString() {
+            return "String !=";
+        }
+    }
+
+    protected static class ObjectEqualsComparator {
+
+        // trying to implement runtime type coercion
+        public boolean equals( Object arg0, Object arg1 ) {
+            if ( arg0 == null ) {
+                return arg1 == null;
+            }
+            if( arg1 != null && arg1 instanceof ShadowProxy ) {
+                return arg1.equals( arg0 );
+            }
+            if( arg0 instanceof Number ){
+                double val0 = ((Number) arg0).doubleValue();
+                double val1 = 0;
+                if( arg1 instanceof Number ) {
+                    val1 = ((Number) arg1).doubleValue();
+                } else if( arg1 instanceof String ) {
+                    val1 = Double.parseDouble( ( String ) arg1 );
+                } else {
+                    throw new ClassCastException( "Not possible to convert "+arg1.getClass()+" into a double value to compare it to "+arg0.getClass() );
+                }
+                return val0 == val1; // in the future we may need to handle rounding errors 
+            } 
+            if( arg0 instanceof String ) {
+                return arg0.equals( arg1.toString() );
+            }
+            if( arg0 instanceof Boolean ) {
+                if( arg1 instanceof String ) {
+                    return ((Boolean)arg0).booleanValue() == Boolean.valueOf( (String)arg1 ).booleanValue();
+                }
+            }
+            if( arg0 instanceof Character ) {
+                if( arg1 instanceof String && ((String) arg1).length() == 1 ) {
+                    return ((Character)arg0).charValue() == ((String)arg1).charAt( 0 );
+                }
+            }
+            return arg0.equals( arg1 );
+        }
+    }
+    
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/EvaluatorCache.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/EvaluatorCache.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/EvaluatorCache.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 6, 2007
+ */
+package org.drools.base.evaluators;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.ValueType;
+import org.drools.spi.Evaluator;
+
+/**
+ * A simple helper class to store Evaluators for a given set of 
+ * value types and operators
+ * 
+ * @author etirelli
+ */
+public class EvaluatorCache implements Serializable {
+    
+
+    private static final long serialVersionUID = 5643974484372543392L;
+    private Map<ValueType, Map<Operator, Evaluator>> evaluators = new HashMap<ValueType, Map<Operator, Evaluator>>();
+    
+    public EvaluatorCache() {
+    }
+    
+    public void addEvaluator( final ValueType type, final Operator operator, final Evaluator evaluator ) {
+        Map<Operator, Evaluator> opEvalMap = this.evaluators.get( type );
+        if( opEvalMap == null ) {
+            opEvalMap = new HashMap<Operator, Evaluator>();
+            this.evaluators.put( type, opEvalMap );
+        }
+        opEvalMap.put( operator, evaluator );
+    }
+    
+    public Evaluator getEvaluator( final ValueType type, final Operator operator ) {
+        Map<Operator, Evaluator> opEvalMap = this.evaluators.get( type );
+        return opEvalMap != null ? opEvalMap.get( operator ) : null;
+    }
+
+    public boolean supportsType(ValueType type) {
+        return this.evaluators.containsKey( type );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/EvaluatorDefinition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/EvaluatorDefinition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/EvaluatorDefinition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 6, 2007
+ */
+package org.drools.base.evaluators;
+
+import org.drools.base.ValueType;
+import org.drools.spi.Evaluator;
+
+/**
+ * An evaluator definition interface that allows for pluggable
+ * evaluator implementation.
+ * 
+ * This interface is the registry entry point for all available
+ * evaluators and describes all evaluator capabilities
+ * 
+ * @author etirelli
+ */
+public interface EvaluatorDefinition {
+
+    /**
+     * Returns the list of identifies this
+     * evaluator implementation supports
+     * 
+     * @return
+     */
+    public String[] getEvaluatorIds();
+
+    /**
+     * My appologies to english speakers if the word "negatable" does not
+     * exists. :)
+     * 
+     * This method returns true if this evaluator supports negation. Example:
+     * 
+     * the "matches" operator supports "not matches" and so is "negatable" (!?)
+     * 
+     * @return
+     */
+    public boolean isNegatable();
+
+    /**
+     * Returns the evaluator instance for the given type and the
+     * defined parameterText
+     * 
+     * @param type the type of the attributes this evaluator will 
+     *             operate on. This is important because the evaluator
+     *             may do optimizations and type coercion based on the 
+     *             types it is evaluating. It is also possible that 
+     *             this evaluator does not support a given type.
+     *             
+     * @param operatorId the string identifier of the evaluator           
+     *             
+     * @param isNegated true if the evaluator instance to be returned is
+     *                  the negated version of the evaluator.
+     *              
+     * @param parameterText some evaluators support parameters and these 
+     *                      parameters are defined as a String that is 
+     *                      parsed by the evaluator itself.
+     *                       
+     * @return an Evaluator instance capable of evaluating expressions
+     *         between values of the given type, or null in case the type
+     *         is not supported. 
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  String operatorId,
+                                  boolean isNegated,
+                                  String parameterText);
+
+    /**
+     * Returns the evaluator instance for the given type and the
+     * defined parameterText
+     * 
+     * @param type the type of the attributes this evaluator will 
+     *             operate on. This is important because the evaluator
+     *             may do optimizations and type coercion based on the 
+     *             types it is evaluating. It is also possible that 
+     *             this evaluator does not support a given type.
+     *             
+     * @param operator the operator implemented by the evaluator           
+     *             
+     * @param parameterText some evaluators support parameters and these 
+     *                      parameters are defined as a String that is 
+     *                      parsed by the evaluator itself.
+     *                       
+     * @return an Evaluator instance capable of evaluating expressions
+     *         between values of the given type, or null in case the type
+     *         is not supported. 
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator,
+                                  String parameterText);
+
+    /**
+     * Returns the evaluator instance for the given type and the
+     * defined parameterText
+     * 
+     * @param type the type of the attributes this evaluator will 
+     *             operate on. This is important because the evaluator
+     *             may do optimizations and type coercion based on the 
+     *             types it is evaluating. It is also possible that 
+     *             this evaluator does not support a given type.
+     *             
+     * @param operator the operator implemented by the evaluator           
+     *             
+     * @return an Evaluator instance capable of evaluating expressions
+     *         between values of the given type, or null in case the type
+     *         is not supported. 
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator);
+
+    /**
+     * Returns true in case this evaluator supports operations over values 
+     * of that specific type.
+     * 
+     * @param type
+     * @return
+     */
+    public boolean supportsType(ValueType type);
+
+    /**
+     * There are evaluators that operate on *fact handle* attributes and 
+     * evaluators that operate on *fact* attributes.
+     * 
+     * @return true if this evaluator operates on fact handle attributes
+     *         and false if it operates on fact attributes
+     */
+    public boolean operatesOnFactHandles();
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/EvaluatorRegistry.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/EvaluatorRegistry.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/EvaluatorRegistry.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 6, 2007
+ */
+package org.drools.base.evaluators;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.ValueType;
+import org.drools.spi.Evaluator;
+
+/**
+ * A registry class for all available evaluators
+ * 
+ * @author etirelli
+ */
+public class EvaluatorRegistry
+    implements
+    Serializable {
+
+    private static final long                serialVersionUID = -3047718531857258033L;
+
+    private Map<String, EvaluatorDefinition> evaluators;
+    private ClassLoader                      classloader;
+
+    /**
+     * Default constructor. The registry will use the context classloader (if available)
+     * to load the evaluator definition classes or this class classloader if it is 
+     * not available.
+     */
+    public EvaluatorRegistry() {
+        this( null );
+    }
+
+    /**
+     * Creates a new EvaluatorRegistry using the given classloader to load
+     * the evaluator definition classes. 
+     * 
+     * @param classloader the classloader to use to load evaluator definition
+     *                    classes. If it is null, try to obtain the context
+     *                    classloader. If it is also null, uses the same classloader
+     *                    that loaded this class.
+     *                    
+     */
+    public EvaluatorRegistry(ClassLoader classloader) {
+        this.evaluators = new HashMap<String, EvaluatorDefinition>();
+        if ( classloader != null ) {
+            this.classloader = classloader;
+        } else {
+            this.classloader = Thread.currentThread().getContextClassLoader() != null ? Thread.currentThread().getContextClassLoader() : this.getClass().getClassLoader();
+        }
+        
+        // loading default built in evaluators
+        this.addEvaluatorDefinition( new EqualityEvaluatorsDefinition() );
+        this.addEvaluatorDefinition( new ComparableEvaluatorsDefinition() );
+        this.addEvaluatorDefinition( new SetEvaluatorsDefinition() );
+        this.addEvaluatorDefinition( new MatchesEvaluatorsDefinition() );
+        this.addEvaluatorDefinition( new SoundslikeEvaluatorsDefinition() );
+    }
+
+    /**
+     * Adds an evaluator definition class to the registry using the
+     * evaluator class name. The class will be loaded and the corresponting
+     * evaluator ID will be added to the registry. In case there exists
+     * an implementation for that ID already, the new implementation will
+     * replace the previous one.
+     * 
+     * @param className the name of the class for the implementation definition.
+     *                  The class must implement the EvaluatorDefinition interface.
+     * 
+     * @return true if the new class implementation is replacing an old
+     *         implementation for the same evaluator ID. False otherwise.
+     */
+    public void addEvaluatorDefinition(String className) {
+        try {
+            Class<EvaluatorDefinition> defClass = (Class<EvaluatorDefinition>) this.classloader.loadClass( className );
+            EvaluatorDefinition def = defClass.newInstance();
+            addEvaluatorDefinition( def );
+        } catch ( ClassNotFoundException e ) {
+            throw new RuntimeDroolsException( "Class not found for evaluator definition: " + className,
+                                              e );
+        } catch ( InstantiationException e ) {
+            throw new RuntimeDroolsException( "Error instantiating class for evaluator definition: " + className,
+                                              e );
+        } catch ( IllegalAccessException e ) {
+            throw new RuntimeDroolsException( "Illegal access instantiating class for evaluator definition: " + className,
+                                              e );
+        }
+    }
+
+    /**
+     * Adds an evaluator definition class to the registry. In case there exists
+     * an implementation for that evaluator ID already, the new implementation will
+     * replace the previous one.
+     * 
+     * @param def the evaluator definition to be added.
+     */
+    public void addEvaluatorDefinition(EvaluatorDefinition def) {
+        for ( String id : def.getEvaluatorIds() ) {
+            this.evaluators.put( id,
+                                 def );
+        }
+    }
+
+    /**
+     * Returns the evaluator definition for the given evaluator ID
+     * or null if no one was found
+     * 
+     * @param evaluatorId
+     * @return
+     */
+    public EvaluatorDefinition getEvaluatorDefinition(String evaluatorId) {
+        return this.evaluators.get( evaluatorId );
+    }
+
+    /**
+     * Returns the evaluator definition for the given operator
+     * or null if no one was found
+     * 
+     * @param operator the operator implemented by the evaluator definition
+     * @return
+     */
+    public EvaluatorDefinition getEvaluatorDefinition(Operator operator) {
+        return this.evaluators.get( operator.getOperatorString() );
+    }
+
+    /**
+     * Returns the evaluator instance for the given type and the
+     * defined parameterText
+     * 
+     * @param type the type of the attributes this evaluator will 
+     *             operate on. This is important because the evaluator
+     *             may do optimizations and type coercion based on the 
+     *             types it is evaluating. It is also possible that 
+     *             this evaluator does not support a given type.
+     *             
+     * @param operatorId the string identifier of the evaluator           
+     *             
+     * @param isNegated true if the evaluator instance to be returned is
+     *                  the negated version of the evaluator.
+     *              
+     * @param parameterText some evaluators support parameters and these 
+     *                      parameters are defined as a String that is 
+     *                      parsed by the evaluator itself.
+     *                       
+     * @return an Evaluator instance capable of evaluating expressions
+     *         between values of the given type, or null in case the type
+     *         is not supported. 
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  String operatorId,
+                                  boolean isNegated,
+                                  String parameterText) {
+        return this.getEvaluatorDefinition( operatorId ).getEvaluator( type,
+                                                                       operatorId,
+                                                                       isNegated,
+                                                                       parameterText );
+    }
+
+    /**
+     * Returns the evaluator instance for the given type and the
+     * defined parameterText
+     * 
+     * @param type the type of the attributes this evaluator will 
+     *             operate on. This is important because the evaluator
+     *             may do optimizations and type coercion based on the 
+     *             types it is evaluating. It is also possible that 
+     *             this evaluator does not support a given type.
+     *             
+     * @param operator the operator that evaluator implements           
+     *             
+     * @param parameterText some evaluators support parameters and these 
+     *                      parameters are defined as a String that is 
+     *                      parsed by the evaluator itself.
+     *                       
+     * @return an Evaluator instance capable of evaluating expressions
+     *         between values of the given type, or null in case the type
+     *         is not supported. 
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator,
+                                  String parameterText) {
+        return this.getEvaluatorDefinition( operator ).getEvaluator( type,
+                                                                     operator,
+                                                                     parameterText );
+    }
+
+    /**
+     * Returns the evaluator instance for the given type and the
+     * defined parameterText
+     * 
+     * @param type the type of the attributes this evaluator will 
+     *             operate on. This is important because the evaluator
+     *             may do optimizations and type coercion based on the 
+     *             types it is evaluating. It is also possible that 
+     *             this evaluator does not support a given type.
+     *             
+     * @param operator the operator that evaluator implements           
+     *             
+     * @return an Evaluator instance capable of evaluating expressions
+     *         between values of the given type, or null in case the type
+     *         is not supported. 
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator) {
+        return this.getEvaluatorDefinition( operator ).getEvaluator( type,
+                                                                     operator );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/FinishedByEvaluatorDefinition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/FinishedByEvaluatorDefinition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/FinishedByEvaluatorDefinition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,274 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 6, 2007
+ */
+package org.drools.base.evaluators;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.BaseEvaluator;
+import org.drools.base.ValueType;
+import org.drools.common.EventFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.VariableRestriction.ObjectVariableContextEntry;
+import org.drools.rule.VariableRestriction.VariableContextEntry;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldValue;
+
+/**
+ * The implementation of the 'finishedby' evaluator definition
+ * 
+ * @author mgroch
+ */
+public class FinishedByEvaluatorDefinition
+    implements
+    EvaluatorDefinition {
+
+    public static final Operator  FINISHED_BY       = Operator.addOperatorToRegistry( "finishedby",
+                                                                                  false );
+    public static final Operator  NOT_FINISHED_BY   = Operator.addOperatorToRegistry( "finishedby",
+                                                                                  true );
+    
+    private static final String[] SUPPORTED_IDS = { FINISHED_BY.getOperatorString() };
+    
+    private Map<String, FinishedByEvaluator> cache        = Collections.emptyMap();
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  null );
+    }
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator,
+                                  String parameterText) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  parameterText );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public Evaluator getEvaluator(final ValueType type,
+                                  final String operatorId,
+                                  final boolean isNegated,
+                                  final String parameterText) {
+        if ( this.cache == Collections.EMPTY_MAP ) {
+            this.cache = new HashMap<String, FinishedByEvaluator>();
+        }
+        String key = isNegated + ":" + parameterText;
+        FinishedByEvaluator eval = this.cache.get( key );
+        if ( eval == null ) {
+            eval = new FinishedByEvaluator( type,
+                                       isNegated,
+                                       parameterText );
+            this.cache.put( key,
+                            eval );
+        }
+        return eval;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public String[] getEvaluatorIds() {
+        return SUPPORTED_IDS;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean isNegatable() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean operatesOnFactHandles() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean supportsType(ValueType type) {
+        // supports all types, since it operates over fact handles
+        // Note: should we change this interface to allow checking of event classes only?
+        return true;
+    }
+
+    /**
+     * Implements the 'finishedby' evaluator itself
+     */
+    public static class FinishedByEvaluator extends BaseEvaluator {
+		private static final long serialVersionUID = -5156972073099070733L;
+		
+		private long                  startMinDev, startMaxDev;
+        private long                  endDev;
+
+        public FinishedByEvaluator(final ValueType type,
+                              final boolean isNegated,
+                              final String parameters) {
+            super( type,
+                   isNegated ? NOT_FINISHED_BY : FINISHED_BY );
+            this.parseParameters( parameters );
+        }
+        
+        @Override
+        public Object prepareObject(InternalFactHandle handle) {
+            return handle;
+        }
+        
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            throw new RuntimeDroolsException( "The 'finishedby' operator can only be used to compare one event to another, and never to compare to literal constraints." );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                final VariableContextEntry context,
+                final Object left) {
+			
+        	if ( context.rightNull ) {
+        		return false;
+				}
+			long distStart = ((EventFactHandle) left ).getStartTimestamp() - ((EventFactHandle)((ObjectVariableContextEntry) context).right).getStartTimestamp();
+			long distEnd = Math.abs(((EventFactHandle) left ).getEndTimestamp() - ((EventFactHandle)((ObjectVariableContextEntry) context).right).getEndTimestamp());
+			return this.getOperator().isNegated() ^ ( distStart >= this.startMinDev && distStart <= this.startMaxDev 
+					&& distEnd <= this.endDev );
+		}
+			
+		public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+			               final VariableContextEntry context,
+			               final Object right) {
+			if ( context.extractor.isNullValue( workingMemory,
+			                     right ) ) {
+			return false;
+			}
+			long distStart = ((EventFactHandle) ((ObjectVariableContextEntry) context).left).getStartTimestamp() - ((EventFactHandle) right ).getStartTimestamp();
+			long distEnd = Math.abs(((EventFactHandle) ((ObjectVariableContextEntry) context).left).getEndTimestamp() - ((EventFactHandle) right ).getEndTimestamp());
+			return this.getOperator().isNegated() ^ ( distStart >= this.startMinDev && distStart <= this.startMaxDev 
+					&& distEnd <= this.endDev );
+		}
+			
+		public boolean evaluate(InternalWorkingMemory workingMemory,
+			     final Extractor extractor1,
+			     final Object object1,
+			     final Extractor extractor2,
+			     final Object object2) {
+			if ( extractor1.isNullValue( workingMemory,
+			              object1 ) ) {
+			return false;
+			}
+			long distStart = ((EventFactHandle) object2 ).getStartTimestamp() - ((EventFactHandle) object1 ).getStartTimestamp();
+			long distEnd = Math.abs(((EventFactHandle) object2 ).getEndTimestamp() - ((EventFactHandle) object1 ).getEndTimestamp());
+			return this.getOperator().isNegated() ^ ( distStart >= this.startMinDev && distStart <= this.startMaxDev 
+					&& distEnd <= this.endDev );
+		}
+
+        public String toString() {
+            return "finishedby[" + startMinDev + ", " + startMaxDev + ", " + endDev + "]";
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int PRIME = 31;
+            int result = super.hashCode();
+            result = PRIME * result + (int) (endDev ^ (endDev >>> 32));
+            result = PRIME * result + (int) (startMaxDev ^ (startMaxDev >>> 32));
+            result = PRIME * result + (int) (startMinDev ^ (startMinDev >>> 32));
+            return result;
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#equals(java.lang.Object)
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if ( this == obj ) return true;
+            if ( !super.equals( obj ) ) return false;
+            if ( getClass() != obj.getClass() ) return false;
+            final FinishedByEvaluator other = (FinishedByEvaluator) obj;
+            return endDev == other.endDev && startMaxDev == other.startMaxDev && startMinDev == other.startMinDev;
+        }
+
+        /**
+         * This methods tries to parse the string of parameters to customize 
+         * the evaluator.
+         * 
+         * @param parameters
+         */
+        private void parseParameters(String parameters) {
+        	if ( parameters == null || parameters.trim().length() == 0 ) {
+                // exact matching at the end of the intervals, open bounded range for the starts
+                this.startMinDev = 1;
+                this.startMaxDev = Long.MAX_VALUE;
+                this.endDev = 0;
+                return;
+            }
+
+            try {
+                String[] ranges = parameters.split( "," );
+                if ( ranges.length == 1 ) {
+                    // exact matching at the end of the intervals
+                	// deterministic point in time for deviations of the starts of the intervals
+                	this.startMinDev = Long.parseLong( ranges[0] );
+                    this.startMaxDev = this.startMinDev;
+                    this.endDev = 0;
+                } else if ( ranges.length == 2 ) {
+                    // exact matching at the end of the intervals
+                	// range for deviations of the starts of the intervals 
+                    this.startMinDev = Long.parseLong( ranges[0] );
+                    this.startMaxDev = Long.parseLong( ranges[1] );
+                    this.endDev = 0;
+                } else if ( ranges.length == 3 ) {
+                	// max. deviation at the ends of the intervals
+                	// range for deviations of the starts of the intervals 
+                    this.startMinDev = Long.parseLong( ranges[0] );
+                    this.startMaxDev = Long.parseLong( ranges[1] );
+                    this.endDev = Long.parseLong( ranges[2] );
+                } else {
+                    throw new RuntimeDroolsException( "[FinishedBy Evaluator]: Not possible to parse parameters: '" + parameters + "'" );
+                }
+            } catch ( NumberFormatException e ) {
+                throw new RuntimeDroolsException( "[FinishedBy Evaluator]: Not possible to parse parameters: '" + parameters + "'",
+                                                  e );
+            }
+        }
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/FinishesEvaluatorDefinition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/FinishesEvaluatorDefinition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/FinishesEvaluatorDefinition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,274 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 6, 2007
+ */
+package org.drools.base.evaluators;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.BaseEvaluator;
+import org.drools.base.ValueType;
+import org.drools.common.EventFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.VariableRestriction.ObjectVariableContextEntry;
+import org.drools.rule.VariableRestriction.VariableContextEntry;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldValue;
+
+/**
+ * The implementation of the 'finishes' evaluator definition
+ * 
+ * @author mgroch
+ */
+public class FinishesEvaluatorDefinition
+    implements
+    EvaluatorDefinition {
+
+    public static final Operator  FINISHES       = Operator.addOperatorToRegistry( "finishes",
+                                                                                  false );
+    public static final Operator  FINISHES_NOT   = Operator.addOperatorToRegistry( "finishes",
+                                                                                  true );
+    
+    private static final String[] SUPPORTED_IDS = { FINISHES.getOperatorString() };
+    
+    private Map<String, FinishesEvaluator> cache        = Collections.emptyMap();
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  null );
+    }
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator,
+                                  String parameterText) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  parameterText );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public Evaluator getEvaluator(final ValueType type,
+                                  final String operatorId,
+                                  final boolean isNegated,
+                                  final String parameterText) {
+        if ( this.cache == Collections.EMPTY_MAP ) {
+            this.cache = new HashMap<String, FinishesEvaluator>();
+        }
+        String key = isNegated + ":" + parameterText;
+        FinishesEvaluator eval = this.cache.get( key );
+        if ( eval == null ) {
+            eval = new FinishesEvaluator( type,
+                                       isNegated,
+                                       parameterText );
+            this.cache.put( key,
+                            eval );
+        }
+        return eval;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public String[] getEvaluatorIds() {
+        return SUPPORTED_IDS;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean isNegatable() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean operatesOnFactHandles() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean supportsType(ValueType type) {
+        // supports all types, since it operates over fact handles
+        // Note: should we change this interface to allow checking of event classes only?
+        return true;
+    }
+
+    /**
+     * Implements the 'finishes' evaluator itself
+     */
+    public static class FinishesEvaluator extends BaseEvaluator {
+		private static final long serialVersionUID = 6232789044144077522L;
+		
+		private long                  startMinDev, startMaxDev;
+        private long                  endDev;
+
+        public FinishesEvaluator(final ValueType type,
+                              final boolean isNegated,
+                              final String parameters) {
+            super( type,
+                   isNegated ? FINISHES_NOT : FINISHES );
+            this.parseParameters( parameters );
+        }
+        
+        @Override
+        public Object prepareObject(InternalFactHandle handle) {
+            return handle;
+        }
+        
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            throw new RuntimeDroolsException( "The 'finishes' operator can only be used to compare one event to another, and never to compare to literal constraints." );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                final VariableContextEntry context,
+                final Object left) {
+			
+        	if ( context.rightNull ) {
+        		return false;
+				}
+			long distStart = ((EventFactHandle)((ObjectVariableContextEntry) context).right).getStartTimestamp() - ((EventFactHandle) left ).getStartTimestamp();
+			long distEnd = Math.abs(((EventFactHandle) left ).getEndTimestamp() - ((EventFactHandle)((ObjectVariableContextEntry) context).right).getEndTimestamp());
+			return this.getOperator().isNegated() ^ ( distStart >= this.startMinDev && distStart <= this.startMaxDev 
+					&& distEnd <= this.endDev );
+		}
+			
+		public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+			               final VariableContextEntry context,
+			               final Object right) {
+			if ( context.extractor.isNullValue( workingMemory,
+			                     right ) ) {
+			return false;
+			}
+			long distStart = ((EventFactHandle) right ).getStartTimestamp() - ((EventFactHandle) ((ObjectVariableContextEntry) context).left).getStartTimestamp();
+			long distEnd = Math.abs(((EventFactHandle) ((ObjectVariableContextEntry) context).left).getEndTimestamp() - ((EventFactHandle) right ).getEndTimestamp());
+			return this.getOperator().isNegated() ^ ( distStart >= this.startMinDev && distStart <= this.startMaxDev 
+					&& distEnd <= this.endDev );
+		}
+			
+		public boolean evaluate(InternalWorkingMemory workingMemory,
+			     final Extractor extractor1,
+			     final Object object1,
+			     final Extractor extractor2,
+			     final Object object2) {
+			if ( extractor1.isNullValue( workingMemory,
+			              object1 ) ) {
+			return false;
+			}
+			long distStart = ((EventFactHandle) object1 ).getStartTimestamp() - ((EventFactHandle) object2 ).getStartTimestamp();
+			long distEnd = Math.abs(((EventFactHandle) object2 ).getEndTimestamp() - ((EventFactHandle) object1 ).getEndTimestamp());
+			return this.getOperator().isNegated() ^ ( distStart >= this.startMinDev && distStart <= this.startMaxDev 
+					&& distEnd <= this.endDev );
+		}
+
+        public String toString() {
+            return "finishes[" + startMinDev + ", " + startMaxDev + ", " + endDev + "]";
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int PRIME = 31;
+            int result = super.hashCode();
+            result = PRIME * result + (int) (endDev ^ (endDev >>> 32));
+            result = PRIME * result + (int) (startMaxDev ^ (startMaxDev >>> 32));
+            result = PRIME * result + (int) (startMinDev ^ (startMinDev >>> 32));
+            return result;
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#equals(java.lang.Object)
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if ( this == obj ) return true;
+            if ( !super.equals( obj ) ) return false;
+            if ( getClass() != obj.getClass() ) return false;
+            final FinishesEvaluator other = (FinishesEvaluator) obj;
+            return endDev == other.endDev && startMaxDev == other.startMaxDev && startMinDev == other.startMinDev;
+        }
+
+        /**
+         * This methods tries to parse the string of parameters to customize 
+         * the evaluator.
+         * 
+         * @param parameters
+         */
+        private void parseParameters(String parameters) {
+        	if ( parameters == null || parameters.trim().length() == 0 ) {
+                // exact matching at the end of the intervals, open bounded range for the starts
+                this.startMinDev = 1;
+                this.startMaxDev = Long.MAX_VALUE;
+                this.endDev = 0;
+                return;
+            }
+
+            try {
+                String[] ranges = parameters.split( "," );
+                if ( ranges.length == 1 ) {
+                    // exact matching at the end of the intervals
+                	// deterministic point in time for deviations of the starts of the intervals
+                	this.startMinDev = Long.parseLong( ranges[0] );
+                    this.startMaxDev = this.startMinDev;
+                    this.endDev = 0;
+                } else if ( ranges.length == 2 ) {
+                    // exact matching at the end of the intervals
+                	// range for deviations of the starts of the intervals 
+                    this.startMinDev = Long.parseLong( ranges[0] );
+                    this.startMaxDev = Long.parseLong( ranges[1] );
+                    this.endDev = 0;
+                } else if ( ranges.length == 3 ) {
+                	// max. deviation at the ends of the intervals
+                	// range for deviations of the starts of the intervals 
+                    this.startMinDev = Long.parseLong( ranges[0] );
+                    this.startMaxDev = Long.parseLong( ranges[1] );
+                    this.endDev = Long.parseLong( ranges[2] );
+                } else {
+                    throw new RuntimeDroolsException( "[Finishes Evaluator]: Not possible to parse parameters: '" + parameters + "'" );
+                }
+            } catch ( NumberFormatException e ) {
+                throw new RuntimeDroolsException( "[Finishes Evaluator]: Not possible to parse parameters: '" + parameters + "'",
+                                                  e );
+            }
+        }
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/IncludesEvaluatorDefinition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/IncludesEvaluatorDefinition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/IncludesEvaluatorDefinition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 6, 2007
+ */
+package org.drools.base.evaluators;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.BaseEvaluator;
+import org.drools.base.ValueType;
+import org.drools.common.EventFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.VariableRestriction.ObjectVariableContextEntry;
+import org.drools.rule.VariableRestriction.VariableContextEntry;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldValue;
+
+/**
+ * The implementation of the 'includes' evaluator definition
+ * 
+ * @author mgroch
+ */
+public class IncludesEvaluatorDefinition
+    implements
+    EvaluatorDefinition {
+
+    public static final Operator  INCLUDES       = Operator.addOperatorToRegistry( "includes",
+                                                                                  false );
+    public static final Operator  INCLUDES_NOT   = Operator.addOperatorToRegistry( "includes",
+                                                                                  true );
+    
+    private static final String[] SUPPORTED_IDS = { INCLUDES.getOperatorString() };
+    
+    private Map<String, IncludesEvaluator> cache        = Collections.emptyMap();
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  null );
+    }
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator,
+                                  String parameterText) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  parameterText );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public Evaluator getEvaluator(final ValueType type,
+                                  final String operatorId,
+                                  final boolean isNegated,
+                                  final String parameterText) {
+        if ( this.cache == Collections.EMPTY_MAP ) {
+            this.cache = new HashMap<String, IncludesEvaluator>();
+        }
+        String key = isNegated + ":" + parameterText;
+        IncludesEvaluator eval = this.cache.get( key );
+        if ( eval == null ) {
+            eval = new IncludesEvaluator( type,
+                                       isNegated,
+                                       parameterText );
+            this.cache.put( key,
+                            eval );
+        }
+        return eval;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public String[] getEvaluatorIds() {
+        return SUPPORTED_IDS;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean isNegatable() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean operatesOnFactHandles() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean supportsType(ValueType type) {
+        // supports all types, since it operates over fact handles
+        // Note: should we change this interface to allow checking of event classes only?
+        return true;
+    }
+
+    /**
+     * Implements the 'includes' evaluator itself
+     */
+    public static class IncludesEvaluator extends BaseEvaluator {
+		private static final long serialVersionUID = -5947397607962049251L;
+		
+		private long                  startMinDev, startMaxDev;
+        private long                  endMinDev, endMaxDev;
+
+        public IncludesEvaluator(final ValueType type,
+                              final boolean isNegated,
+                              final String parameters) {
+            super( type,
+                   isNegated ? INCLUDES_NOT : INCLUDES );
+            this.parseParameters( parameters );
+        }
+        
+        @Override
+        public Object prepareObject(InternalFactHandle handle) {
+            return handle;
+        }
+        
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            throw new RuntimeDroolsException( "The 'includes' operator can only be used to compare one event to another, and never to compare to literal constraints." );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                final VariableContextEntry context,
+                final Object left) {
+			
+        	if ( context.rightNull ) {
+        		return false;
+				}
+			long distStart = ((EventFactHandle) left ).getStartTimestamp() - ((EventFactHandle)((ObjectVariableContextEntry) context).right).getStartTimestamp();
+			long distEnd = ((EventFactHandle)((ObjectVariableContextEntry) context).right).getEndTimestamp() - ((EventFactHandle) left ).getEndTimestamp();
+			return this.getOperator().isNegated() ^ ( distStart >= this.startMinDev && distStart <= this.startMaxDev 
+					&& distEnd >= this.endMinDev && distEnd <= this.endMaxDev );
+		}
+			
+		public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+			               final VariableContextEntry context,
+			               final Object right) {
+			if ( context.extractor.isNullValue( workingMemory,
+			                     right ) ) {
+			return false;
+			}
+			long distStart = ((EventFactHandle) ((ObjectVariableContextEntry) context).left).getStartTimestamp() - ((EventFactHandle) right ).getStartTimestamp();
+			long distEnd = ((EventFactHandle) right ).getEndTimestamp() - ((EventFactHandle) ((ObjectVariableContextEntry) context).left).getEndTimestamp();
+			return this.getOperator().isNegated() ^ ( distStart >= this.startMinDev && distStart <= this.startMaxDev 
+					&& distEnd >= this.endMinDev && distEnd <= this.endMaxDev );
+		}
+			
+		public boolean evaluate(InternalWorkingMemory workingMemory,
+			     final Extractor extractor1,
+			     final Object object1,
+			     final Extractor extractor2,
+			     final Object object2) {
+			if ( extractor1.isNullValue( workingMemory,
+			              object1 ) ) {
+			return false;
+			}
+			long distStart = ((EventFactHandle) object2 ).getStartTimestamp() - ((EventFactHandle) object1 ).getStartTimestamp();
+			long distEnd = ((EventFactHandle) object1 ).getEndTimestamp() - ((EventFactHandle) object2 ).getEndTimestamp();
+			return this.getOperator().isNegated() ^ ( distStart >= this.startMinDev && distStart <= this.startMaxDev 
+					&& distEnd >= this.endMinDev && distEnd <= this.endMaxDev );
+		}
+
+        public String toString() {
+            return "includes[" + startMinDev + ", " + startMaxDev + ", " + endMinDev + ", " + endMaxDev + "]";
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int PRIME = 31;
+            int result = super.hashCode();
+            result = PRIME * result + (int) (endMaxDev ^ (endMaxDev >>> 32));
+            result = PRIME * result + (int) (endMinDev ^ (endMinDev >>> 32));
+            result = PRIME * result + (int) (startMaxDev ^ (startMaxDev >>> 32));
+            result = PRIME * result + (int) (startMinDev ^ (startMinDev >>> 32));
+            return result;
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#equals(java.lang.Object)
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if ( this == obj ) return true;
+            if ( !super.equals( obj ) ) return false;
+            if ( getClass() != obj.getClass() ) return false;
+            final IncludesEvaluator other = (IncludesEvaluator) obj;
+            return endMaxDev == other.endMaxDev && endMinDev == other.endMinDev
+            	&& startMaxDev == other.startMaxDev && startMinDev == other.startMinDev;
+        }
+
+        /**
+         * This methods tries to parse the string of parameters to customize 
+         * the evaluator.
+         * 
+         * @param parameters
+         */
+        private void parseParameters(String parameters) {
+            if ( parameters == null || parameters.trim().length() == 0 ) {
+                // open bounded ranges
+                this.startMinDev = 1;
+                this.startMaxDev = Long.MAX_VALUE;
+                this.endMinDev = 1;
+                this.endMaxDev = Long.MAX_VALUE;
+                return;
+            }
+
+            try {
+                String[] ranges = parameters.split( "," );
+                if ( ranges.length == 1 ) {
+                    // deterministic point in time for deviation of the starts of the intervals 
+                    this.startMinDev = Long.parseLong( ranges[0] );
+                    this.startMaxDev = this.startMinDev;
+                    this.endMinDev = this.startMinDev;
+                    this.endMaxDev = this.startMinDev;
+                } else if ( ranges.length == 2 ) {
+                    // deterministic points in time for deviations of the starts and the ends of the intervals 
+                    this.startMinDev = Long.parseLong( ranges[0] );
+                    this.startMaxDev = this.startMinDev;
+                    this.endMinDev = Long.parseLong( ranges[1] );
+                    this.endMaxDev = this.endMinDev;
+                } else if ( ranges.length == 4 ) {
+                    // ranges for deviations of the starts and the ends of the intervals 
+                	this.startMinDev = Long.parseLong( ranges[0] );
+                    this.startMaxDev = Long.parseLong( ranges[1] );
+                    this.endMinDev = Long.parseLong( ranges[2] );
+                    this.endMaxDev = Long.parseLong( ranges[3] );
+                } else {
+                    throw new RuntimeDroolsException( "[Includes Evaluator]: Not possible to parse parameters: '" + parameters + "'" );
+                }
+            } catch ( NumberFormatException e ) {
+                throw new RuntimeDroolsException( "[Includes Evaluator]: Not possible to parse parameters: '" + parameters + "'",
+                                                  e );
+            }
+        }
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/MatchesEvaluatorsDefinition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/MatchesEvaluatorsDefinition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/MatchesEvaluatorsDefinition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 6, 2007
+ */
+package org.drools.base.evaluators;
+
+import org.drools.base.BaseEvaluator;
+import org.drools.base.ValueType;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.VariableRestriction.ObjectVariableContextEntry;
+import org.drools.rule.VariableRestriction.VariableContextEntry;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldValue;
+
+/**
+ * This class defines the matches evaluator
+ * 
+ * @author etirelli
+ */
+public class MatchesEvaluatorsDefinition implements EvaluatorDefinition {
+    
+    public static final Operator  MATCHES       = Operator.addOperatorToRegistry( "matches",
+                                                                                  false );
+    public static final Operator  NOT_MATCHES   = Operator.addOperatorToRegistry( "matches",
+                                                                                  true );
+    
+    private static final String[] SUPPORTED_IDS = { MATCHES.getOperatorString() };
+    private EvaluatorCache evaluators = new EvaluatorCache() {
+        private static final long serialVersionUID = 4782368623L;
+        {
+            addEvaluator( ValueType.STRING_TYPE,        MATCHES,         StringMatchesEvaluator.INSTANCE );
+            addEvaluator( ValueType.STRING_TYPE,        NOT_MATCHES,     StringNotMatchesEvaluator.INSTANCE );
+        }
+    };
+    
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator) {
+        return this.evaluators.getEvaluator( type,
+                                             operator );
+    }
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator,
+                                  String parameterText) {
+        return this.evaluators.getEvaluator( type,
+                                             operator );
+    }
+
+
+    public Evaluator getEvaluator(final ValueType type,
+                                  final String operatorId,
+                                  final boolean isNegated,
+                                  final String parameterText) {
+        return this.evaluators.getEvaluator( type, Operator.determineOperator( operatorId, isNegated ) );
+    }
+
+    public String[] getEvaluatorIds() {
+        return SUPPORTED_IDS;
+    }
+
+    public boolean isNegatable() {
+        return true;
+    }
+
+    public boolean operatesOnFactHandles() {
+        return false;
+    }
+
+    public boolean supportsType(ValueType type) {
+        return this.evaluators.supportsType( type );
+    }
+
+    /*  *********************************************************
+     *           Evaluator Implementations
+     *  *********************************************************
+     */
+    static class StringMatchesEvaluator extends BaseEvaluator {
+        /**
+         *
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new StringMatchesEvaluator();
+
+        private StringMatchesEvaluator() {
+            super( ValueType.STRING_TYPE,
+                   MATCHES );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            final String value1 = (String) extractor.getValue( workingMemory, object1 );
+            final String value2 = (String) object2.getValue();
+            if ( value1 == null ) {
+                return false;
+            }
+            return value1.matches( value2 );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            final String value = (String) ((ObjectVariableContextEntry) context).right;
+            if ( value == null ) {
+                return false;
+            }
+            return value.matches( (String) context.declaration.getExtractor().getValue( workingMemory, left ) );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            final String value = (String) context.extractor.getValue( workingMemory, right );
+            if ( value == null ) {
+                return false;
+            }
+            return value.matches( (String) ((ObjectVariableContextEntry) context).left );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            final Object value1 = extractor1.getValue( workingMemory, object1 );
+            final Object value2 = extractor2.getValue( workingMemory, object2 );
+            if ( value1 == null ) {
+                return false;
+            }
+            return ((String) value1).matches( (String) value2 );
+        }
+
+        public String toString() {
+            return "String matches";
+        }
+    }
+
+    static class StringNotMatchesEvaluator extends BaseEvaluator {
+        /**
+         *
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new StringNotMatchesEvaluator();
+
+        private StringNotMatchesEvaluator() {
+            super( ValueType.STRING_TYPE,
+                   NOT_MATCHES );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            final String value1 = (String) extractor.getValue( workingMemory, object1 );
+            final String value2 = (String) object2.getValue();
+            if ( value1 == null ) {
+                return false;
+            }
+            return ! value1.matches( value2 );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            final String value = (String) ((ObjectVariableContextEntry) context).right;
+            if ( value == null ) {
+                return false;
+            }
+            return ! value.matches( (String) context.declaration.getExtractor().getValue( workingMemory, left ) );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            final String value = (String) context.extractor.getValue( workingMemory, right );
+            if ( value == null ) {
+                return false;
+            }
+            return ! value.matches( (String) ((ObjectVariableContextEntry) context).left );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            final Object value1 = extractor1.getValue( workingMemory, object1 );
+            final Object value2 = extractor2.getValue( workingMemory, object2 );
+            if ( value1 == null ) {
+                return false;
+            }
+            return ! ((String) value1).matches( (String) value2 );
+        }
+
+        public String toString() {
+            return "String not matches";
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/MeetsEvaluatorDefinition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/MeetsEvaluatorDefinition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/MeetsEvaluatorDefinition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 6, 2007
+ */
+package org.drools.base.evaluators;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.BaseEvaluator;
+import org.drools.base.ValueType;
+import org.drools.common.EventFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.VariableRestriction.ObjectVariableContextEntry;
+import org.drools.rule.VariableRestriction.VariableContextEntry;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldValue;
+
+/**
+ * The implementation of the 'meets' evaluator definition
+ * 
+ * @author mgroch
+ */
+public class MeetsEvaluatorDefinition
+    implements
+    EvaluatorDefinition {
+
+    public static final Operator  MEETS       = Operator.addOperatorToRegistry( "meets",
+                                                                                  false );
+    public static final Operator  MEETS_NOT   = Operator.addOperatorToRegistry( "meets",
+                                                                                  true );
+    
+    private static final String[] SUPPORTED_IDS = { MEETS.getOperatorString() };
+    
+    private Map<String, MeetsEvaluator> cache        = Collections.emptyMap();
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  null );
+    }
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator,
+                                  String parameterText) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  parameterText );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public Evaluator getEvaluator(final ValueType type,
+                                  final String operatorId,
+                                  final boolean isNegated,
+                                  final String parameterText) {
+        if ( this.cache == Collections.EMPTY_MAP ) {
+            this.cache = new HashMap<String, MeetsEvaluator>();
+        }
+        String key = isNegated + ":" + parameterText;
+        MeetsEvaluator eval = this.cache.get( key );
+        if ( eval == null ) {
+            eval = new MeetsEvaluator( type,
+                                       isNegated,
+                                       parameterText );
+            this.cache.put( key,
+                            eval );
+        }
+        return eval;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public String[] getEvaluatorIds() {
+        return SUPPORTED_IDS;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean isNegatable() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean operatesOnFactHandles() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean supportsType(ValueType type) {
+        // supports all types, since it operates over fact handles
+        // Note: should we change this interface to allow checking of event classes only?
+        return true;
+    }
+
+    /**
+     * Implements the 'meets' evaluator itself
+     */
+    public static class MeetsEvaluator extends BaseEvaluator {
+		private static final long serialVersionUID = 9091548399308812447L;
+		
+		private long                  finalRange;
+
+        public MeetsEvaluator(final ValueType type,
+                              final boolean isNegated,
+                              final String parameters) {
+            super( type,
+                   isNegated ? MEETS_NOT : MEETS );
+            this.parseParameters( parameters );
+        }
+        
+        @Override
+        public Object prepareObject(InternalFactHandle handle) {
+            return handle;
+        }
+        
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            throw new RuntimeDroolsException( "The 'meets' operator can only be used to compare one event to another, and never to compare to literal constraints." );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                final VariableContextEntry context,
+                final Object left) {
+			if ( context.rightNull ) {
+			return false;
+			}
+			long leftStartTS = ((EventFactHandle) left ).getStartTimestamp();
+			long dist = Math.abs(leftStartTS - 
+						((EventFactHandle)((ObjectVariableContextEntry) context).right).getEndTimestamp());
+			return this.getOperator().isNegated() ^ ( ((EventFactHandle)((ObjectVariableContextEntry) context).right).getStartTimestamp() <= leftStartTS 
+					&& dist <= this.finalRange );
+		}
+			
+		public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+			               final VariableContextEntry context,
+			               final Object right) {
+			if ( context.extractor.isNullValue( workingMemory,
+			                     right ) ) {
+			return false;
+			}
+			long leftStartTS = ((EventFactHandle) ((ObjectVariableContextEntry) context).left).getStartTimestamp();
+			long dist = Math.abs(leftStartTS - ((EventFactHandle) right ).getEndTimestamp());
+			return this.getOperator().isNegated() ^ ( ((EventFactHandle) right ).getStartTimestamp() <= leftStartTS && dist <= this.finalRange);
+		}
+			
+		public boolean evaluate(InternalWorkingMemory workingMemory,
+			     final Extractor extractor1,
+			     final Object object1,
+			     final Extractor extractor2,
+			     final Object object2) {
+			if ( extractor1.isNullValue( workingMemory,
+			              object1 ) ) {
+			return false;
+			}
+			long obj2StartTS = ((EventFactHandle) object2 ).getStartTimestamp();
+			long dist = Math.abs(obj2StartTS - ((EventFactHandle) object1 ).getEndTimestamp());
+			return this.getOperator().isNegated() ^ ( ((EventFactHandle) object1 ).getStartTimestamp() <= obj2StartTS && dist <= this.finalRange);
+		}
+
+        public String toString() {
+            return "meets[" + finalRange + "]";
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int PRIME = 31;
+            int result = super.hashCode();
+            result = PRIME * result + (int) (finalRange ^ (finalRange >>> 32));
+            return result;
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#equals(java.lang.Object)
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if ( this == obj ) return true;
+            if ( !super.equals( obj ) ) return false;
+            if ( getClass() != obj.getClass() ) return false;
+            final MeetsEvaluator other = (MeetsEvaluator) obj;
+            return finalRange == other.finalRange;
+        }
+
+        /**
+         * This methods tries to parse the string of parameters to customize 
+         * the evaluator.
+         * 
+         * @param parameters
+         */
+        private void parseParameters(String parameters) {
+            if ( parameters == null || parameters.trim().length() == 0 ) {
+                // exact meet
+                this.finalRange = 0;
+                return;
+            }
+
+            try {
+                String[] ranges = parameters.split( "," );
+                if ( ranges.length == 1 ) {
+                	// limit of tolerance for overlap or gap, respectively
+                    this.finalRange = Long.parseLong( ranges[0] );
+                } else {
+                    throw new RuntimeDroolsException( "[Meets Evaluator]: Not possible to parse parameters: '" + parameters + "'" );
+                }
+            } catch ( NumberFormatException e ) {
+                throw new RuntimeDroolsException( "[Meets Evaluator]: Not possible to parse parameters: '" + parameters + "'",
+                                                  e );
+            }
+        }
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/MetByEvaluatorDefinition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/MetByEvaluatorDefinition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/MetByEvaluatorDefinition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 6, 2007
+ */
+package org.drools.base.evaluators;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.BaseEvaluator;
+import org.drools.base.ValueType;
+import org.drools.common.EventFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.VariableRestriction.ObjectVariableContextEntry;
+import org.drools.rule.VariableRestriction.VariableContextEntry;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldValue;
+
+/**
+ * The implementation of the 'metby' evaluator definition
+ * 
+ * @author mgroch
+ */
+public class MetByEvaluatorDefinition
+    implements
+    EvaluatorDefinition {
+
+    public static final Operator  MET_BY       = Operator.addOperatorToRegistry( "metby",
+                                                                                  false );
+    public static final Operator  NOT_MET_BY   = Operator.addOperatorToRegistry( "metby",
+                                                                                  true );
+    
+    private static final String[] SUPPORTED_IDS = { MET_BY.getOperatorString() };
+    
+    private Map<String, MetByEvaluator> cache        = Collections.emptyMap();
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  null );
+    }
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator,
+                                  String parameterText) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  parameterText );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public Evaluator getEvaluator(final ValueType type,
+                                  final String operatorId,
+                                  final boolean isNegated,
+                                  final String parameterText) {
+        if ( this.cache == Collections.EMPTY_MAP ) {
+            this.cache = new HashMap<String, MetByEvaluator>();
+        }
+        String key = isNegated + ":" + parameterText;
+        MetByEvaluator eval = this.cache.get( key );
+        if ( eval == null ) {
+            eval = new MetByEvaluator( type,
+                                       isNegated,
+                                       parameterText );
+            this.cache.put( key,
+                            eval );
+        }
+        return eval;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public String[] getEvaluatorIds() {
+        return SUPPORTED_IDS;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean isNegatable() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean operatesOnFactHandles() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean supportsType(ValueType type) {
+        // supports all types, since it operates over fact handles
+        // Note: should we change this interface to allow checking of event classes only?
+        return true;
+    }
+
+    /**
+     * Implements the 'metby' evaluator itself
+     */
+    public static class MetByEvaluator extends BaseEvaluator {
+		private static final long serialVersionUID = 7907908401657594347L;
+		
+		private long                  finalRange;
+
+        public MetByEvaluator(final ValueType type,
+                              final boolean isNegated,
+                              final String parameters) {
+            super( type,
+                   isNegated ? NOT_MET_BY : MET_BY );
+            this.parseParameters( parameters );
+        }
+        
+        @Override
+        public Object prepareObject(InternalFactHandle handle) {
+            return handle;
+        }
+        
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            throw new RuntimeDroolsException( "The 'metby' operator can only be used to compare one event to another, and never to compare to literal constraints." );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context,
+                                           final Object left) {
+            if ( context.rightNull ) {
+                return false;
+            }
+            long rightStartTS = ((EventFactHandle)((ObjectVariableContextEntry) context).right).getStartTimestamp();
+            long dist = Math.abs(rightStartTS - ((EventFactHandle) left ).getEndTimestamp());
+            return this.getOperator().isNegated() ^ ( ((EventFactHandle) left ).getStartTimestamp() < rightStartTS && dist <= this.finalRange );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context,
+                                          final Object right) {
+            if ( context.extractor.isNullValue( workingMemory,
+                                                right ) ) {
+                return false;
+            }
+            long rightStartTS = ((EventFactHandle) right ).getStartTimestamp();
+            long dist = Math.abs(rightStartTS - ((EventFactHandle) ((ObjectVariableContextEntry) context).left).getEndTimestamp());
+
+            return this.getOperator().isNegated() ^ ( ((EventFactHandle) ((ObjectVariableContextEntry) context).left).getStartTimestamp() <= rightStartTS && 
+            	    dist <= this.finalRange );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2,
+                                final Object object2) {
+            if ( extractor1.isNullValue( workingMemory,
+                                         object1 ) ) {
+                return false;
+            }
+            long obj1StartTS = ((EventFactHandle) object1 ).getStartTimestamp();
+            long dist = Math.abs(obj1StartTS - ((EventFactHandle) object2 ).getEndTimestamp());
+            return this.getOperator().isNegated() ^ ( ((EventFactHandle) object2 ).getStartTimestamp() <= obj1StartTS && dist <= this.finalRange );
+        }
+
+        public String toString() {
+            return "metby[" + finalRange + "]";
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int PRIME = 31;
+            int result = super.hashCode();
+            result = PRIME * result + (int) (finalRange ^ (finalRange >>> 32));
+            return result;
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#equals(java.lang.Object)
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if ( this == obj ) return true;
+            if ( !super.equals( obj ) ) return false;
+            if ( getClass() != obj.getClass() ) return false;
+            final MetByEvaluator other = (MetByEvaluator) obj;
+            return finalRange == other.finalRange;
+        }
+
+        /**
+         * This methods tries to parse the string of parameters to customize 
+         * the evaluator.
+         * 
+         * @param parameters
+         */
+        private void parseParameters(String parameters) {
+            if ( parameters == null || parameters.trim().length() == 0 ) {
+                // exact metby
+                this.finalRange = 0;
+                return;
+            }
+
+            try {
+                String[] ranges = parameters.split( "," );
+                if ( ranges.length == 1 ) {
+                    // limit of tolerance for overlap or gap, respectively
+                    this.finalRange = Long.parseLong( ranges[0] );
+                } else {
+                    throw new RuntimeDroolsException( "[Metby Evaluator]: Not possible to parse parameters: '" + parameters + "'" );
+                }
+            } catch ( NumberFormatException e ) {
+                throw new RuntimeDroolsException( "[Metby Evaluator]: Not possible to parse parameters: '" + parameters + "'",
+                                                  e );
+            }
+        }
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/Operator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/Operator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/Operator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,127 @@
+package org.drools.base.evaluators;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+
+public class Operator
+    implements
+    Serializable {
+
+    private static final long                  serialVersionUID = 400L;
+
+    // a static private cache so that pluggable operator can register their implementations
+    // it is automatically initialized with common operator implementations
+    private static final Map<String, Operator> CACHE            = Collections.synchronizedMap( new HashMap<String, Operator>() );
+
+    // these static operator constants are kept here just to make it easier for the engine
+    // to reference common used operators. The addition of new constants here is not
+    // advisable though.
+    public static final Operator               EQUAL            = addOperatorToRegistry( "==",
+                                                                                         false );
+    public static final Operator               NOT_EQUAL        = addOperatorToRegistry( "!=",
+                                                                                         false );
+    public static final Operator               LESS             = addOperatorToRegistry( "<",
+                                                                                         false );
+    public static final Operator               LESS_OR_EQUAL    = addOperatorToRegistry( "<=",
+                                                                                         false );
+    public static final Operator               GREATER          = addOperatorToRegistry( ">",
+                                                                                         false );
+    public static final Operator               GREATER_OR_EQUAL = addOperatorToRegistry( ">=",
+                                                                                         false );
+
+    /**
+     * Creates a new Operator instance for the given parameters, 
+     * adds it to the registry and return it
+     * 
+     * @param operatorId the identification symbol of the operator
+     * @param isNegated true if it is negated
+     * 
+     * @return the newly created operator
+     */
+    public static Operator addOperatorToRegistry(final String operatorId,
+                                                 final boolean isNegated) {
+        Operator op = new Operator( operatorId,
+                                    isNegated );
+        CACHE.put( getKey( operatorId,
+                           isNegated ),
+                   op );
+        return op;
+    }
+
+    /**
+     * Returns the operator instance for the given parameters
+     * 
+     * @param operatorId the identification symbol of the operator
+     * @param isNegated true if it is negated
+     * 
+     * @return the operator in case it exists
+     */
+    public static Operator determineOperator(final String operatorId,
+                                             final boolean isNegated) {
+        Operator op = CACHE.get( getKey( operatorId,
+                                         isNegated ) );
+        if ( op == null ) {
+            throw new RuntimeDroolsException( "unable to determine operator for symbol [" + (isNegated ? "not " : "") + operatorId + "]" );
+        }
+        return op;
+    }
+
+    private static String getKey(final String string,
+                                 final boolean isNegated) {
+        return isNegated + ":" + string;
+    }
+
+    // This class attributes
+    private String  operator;
+    private boolean isNegated;
+
+    private Operator(final String operator,
+                     final boolean isNegated) {
+        this.operator = operator;
+        this.isNegated = isNegated;
+    }
+
+    private Object readResolve() throws java.io.ObjectStreamException {
+        return determineOperator( this.operator,
+                                  this.isNegated );
+    }
+
+    public String toString() {
+        return "Operator = '" + this.operator + "'";
+    }
+
+    public String getOperatorString() {
+        return this.operator;
+    }
+    
+    public boolean isNegated() {
+        return this.isNegated;
+    }
+
+    @Override
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = super.hashCode();
+        result = PRIME * result + (isNegated ? 1231 : 1237);
+        result = PRIME * result + ((operator == null) ? 0 : operator.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if ( this == obj ) return true;
+        if ( obj == null ) return false;
+        if ( getClass() != obj.getClass() ) return false;
+        final Operator other = (Operator) obj;
+        if ( isNegated != other.isNegated ) return false;
+        if ( operator == null ) {
+            if ( other.operator != null ) return false;
+        } else if ( !operator.equals( other.operator ) ) return false;
+        return true;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/OverlappedByEvaluatorDefinition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/OverlappedByEvaluatorDefinition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/OverlappedByEvaluatorDefinition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,282 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 6, 2007
+ */
+package org.drools.base.evaluators;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.BaseEvaluator;
+import org.drools.base.ValueType;
+import org.drools.common.EventFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.VariableRestriction.ObjectVariableContextEntry;
+import org.drools.rule.VariableRestriction.VariableContextEntry;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldValue;
+
+/**
+ * The implementation of the 'overlappedby' evaluator definition
+ * 
+ * @author mgroch
+ */
+public class OverlappedByEvaluatorDefinition
+    implements
+    EvaluatorDefinition {
+
+    public static final Operator  OVERLAPPED_BY       = Operator.addOperatorToRegistry( "overlappedby",
+                                                                                  false );
+    public static final Operator  NOT_OVERLAPPED_BY   = Operator.addOperatorToRegistry( "overlappedby",
+                                                                                  true );
+    
+    private static final String[] SUPPORTED_IDS = { OVERLAPPED_BY.getOperatorString() };
+    
+    private Map<String, OverlappedByEvaluator> cache        = Collections.emptyMap();
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  null );
+    }
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator,
+                                  String parameterText) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  parameterText );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public Evaluator getEvaluator(final ValueType type,
+                                  final String operatorId,
+                                  final boolean isNegated,
+                                  final String parameterText) {
+        if ( this.cache == Collections.EMPTY_MAP ) {
+            this.cache = new HashMap<String, OverlappedByEvaluator>();
+        }
+        String key = isNegated + ":" + parameterText;
+        OverlappedByEvaluator eval = this.cache.get( key );
+        if ( eval == null ) {
+            eval = new OverlappedByEvaluator( type,
+                                       isNegated,
+                                       parameterText );
+            this.cache.put( key,
+                            eval );
+        }
+        return eval;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public String[] getEvaluatorIds() {
+        return SUPPORTED_IDS;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean isNegatable() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean operatesOnFactHandles() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean supportsType(ValueType type) {
+        // supports all types, since it operates over fact handles
+        // Note: should we change this interface to allow checking of event classes only?
+        return true;
+    }
+
+    /**
+     * Implements the 'overlappedby' evaluator itself
+     */
+    public static class OverlappedByEvaluator extends BaseEvaluator {
+		private static final long serialVersionUID = -2768899194494247889L;
+		
+		private long                  startMinDev, startMaxDev;
+        private long                  endMinDev, endMaxDev;
+
+        public OverlappedByEvaluator(final ValueType type,
+                              final boolean isNegated,
+                              final String parameters) {
+            super( type,
+                   isNegated ? NOT_OVERLAPPED_BY : OVERLAPPED_BY );
+            this.parseParameters( parameters );
+        }
+        
+        @Override
+        public Object prepareObject(InternalFactHandle handle) {
+            return handle;
+        }
+        
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            throw new RuntimeDroolsException( "The 'overlappedby' operator can only be used to compare one event to another, and never to compare to literal constraints." );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context,
+                                           final Object left) {
+            if ( context.rightNull ) {
+                return false;
+            }
+            long rightStartTS = ((EventFactHandle)((ObjectVariableContextEntry) context).right).getStartTimestamp();
+			long leftEndTS = ((EventFactHandle) left ).getEndTimestamp();
+            long distStart = rightStartTS - ((EventFactHandle) left ).getStartTimestamp();
+            long distEnd = ((EventFactHandle)((ObjectVariableContextEntry) context).right).getEndTimestamp() - leftEndTS;
+            return this.getOperator().isNegated() ^ ( distStart >= this.startMinDev && distStart <= this.startMaxDev 
+            		&& distEnd >= this.endMinDev && distEnd <= this.endMaxDev && rightStartTS < leftEndTS );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context,
+                                          final Object right) {
+            if ( context.extractor.isNullValue( workingMemory,
+                                                right ) ) {
+                return false;
+            }
+            long leftEndTS = ((EventFactHandle) ((ObjectVariableContextEntry) context).left).getEndTimestamp();
+			long rightStartTS = ((EventFactHandle) right ).getStartTimestamp();
+            long distStart = rightStartTS - ((EventFactHandle) ((ObjectVariableContextEntry) context).left).getStartTimestamp();
+            long distEnd = ((EventFactHandle) right ).getEndTimestamp() - leftEndTS;
+            return this.getOperator().isNegated() ^ ( distStart >= this.startMinDev && distStart <= this.startMaxDev 
+            		&& distEnd >= this.endMinDev && distEnd <= this.endMaxDev && rightStartTS < leftEndTS );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2,
+                                final Object object2) {
+            if ( extractor1.isNullValue( workingMemory,
+                                         object1 ) ) {
+                return false;
+            }
+            long o1startTS = ((EventFactHandle) object1 ).getStartTimestamp();
+            long o2endTS = ((EventFactHandle) object2 ).getEndTimestamp();
+            long distStart = o1startTS - ((EventFactHandle) object2 ).getStartTimestamp();
+            long distEnd = ((EventFactHandle) object1 ).getEndTimestamp() - o2endTS;
+            return this.getOperator().isNegated() ^ ( distStart >= this.startMinDev && distStart <= this.startMaxDev 
+            		&& distEnd >= this.endMinDev && distEnd <= this.endMaxDev && o1startTS < o2endTS );
+        }
+
+        public String toString() {
+            return "overlappedby[" + startMinDev + ", " + startMaxDev + ", " + endMinDev + ", " + endMaxDev + "]";
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int PRIME = 31;
+            int result = super.hashCode();
+            result = PRIME * result + (int) (endMaxDev ^ (endMaxDev >>> 32));
+            result = PRIME * result + (int) (endMinDev ^ (endMinDev >>> 32));
+            result = PRIME * result + (int) (startMaxDev ^ (startMaxDev >>> 32));
+            result = PRIME * result + (int) (startMinDev ^ (startMinDev >>> 32));
+            return result;
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#equals(java.lang.Object)
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if ( this == obj ) return true;
+            if ( !super.equals( obj ) ) return false;
+            if ( getClass() != obj.getClass() ) return false;
+            final OverlappedByEvaluator other = (OverlappedByEvaluator) obj;
+            return endMaxDev == other.endMaxDev && endMinDev == other.endMinDev
+            	&& startMaxDev == other.startMaxDev && startMinDev == other.startMinDev;
+        }
+
+        /**
+         * This methods tries to parse the string of parameters to customize 
+         * the evaluator.
+         * 
+         * @param parameters
+         */
+        private void parseParameters(String parameters) {
+            if ( parameters == null || parameters.trim().length() == 0 ) {
+            	// open bounded ranges
+                this.startMinDev = 1;
+                this.startMaxDev = Long.MAX_VALUE;
+                this.endMinDev = 1;
+                this.endMaxDev = Long.MAX_VALUE;
+                return;
+            }
+
+            try {
+                String[] ranges = parameters.split( "," );
+                if ( ranges.length == 1 ) {
+                    // deterministic point in time for deviation of the starts of the intervals 
+                	this.startMinDev = Long.parseLong( ranges[0] );
+                    this.startMaxDev = this.startMinDev;
+                    this.endMinDev = this.startMinDev;
+                    this.endMaxDev = this.startMinDev;
+                } else if ( ranges.length == 2 ) {
+                    // deterministic points in time for deviations of the starts and the ends of the intervals 
+                    this.startMinDev = Long.parseLong( ranges[0] );
+                    this.startMaxDev = this.startMinDev;
+                    this.endMinDev = Long.parseLong( ranges[1] );
+                    this.endMaxDev = this.endMinDev;
+                } else if ( ranges.length == 4 ) {
+                    // ranges for deviations of the starts and the ends of the intervals 
+                	this.startMinDev = Long.parseLong( ranges[0] );
+                    this.startMaxDev = Long.parseLong( ranges[1] );
+                    this.endMinDev = Long.parseLong( ranges[2] );
+                    this.endMaxDev = Long.parseLong( ranges[3] );
+                } else {
+                    throw new RuntimeDroolsException( "[Overlappedby Evaluator]: Not possible to parse parameters: '" + parameters + "'" );
+                }
+            } catch ( NumberFormatException e ) {
+                throw new RuntimeDroolsException( "[Overlappedby Evaluator]: Not possible to parse parameters: '" + parameters + "'",
+                                                  e );
+            }
+        }
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/OverlapsEvaluatorDefinition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/OverlapsEvaluatorDefinition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/OverlapsEvaluatorDefinition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 6, 2007
+ */
+package org.drools.base.evaluators;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.BaseEvaluator;
+import org.drools.base.ValueType;
+import org.drools.common.EventFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.VariableRestriction.ObjectVariableContextEntry;
+import org.drools.rule.VariableRestriction.VariableContextEntry;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldValue;
+
+/**
+ * The implementation of the 'overlaps' evaluator definition
+ * 
+ * @author mgroch
+ */
+public class OverlapsEvaluatorDefinition
+    implements
+    EvaluatorDefinition {
+
+    public static final Operator  OVERLAPS       = Operator.addOperatorToRegistry( "overlaps",
+                                                                                  false );
+    public static final Operator  OVERLAPS_NOT   = Operator.addOperatorToRegistry( "overlaps",
+                                                                                  true );
+    
+    private static final String[] SUPPORTED_IDS = { OVERLAPS.getOperatorString() };
+    
+    private Map<String, OverlapsEvaluator> cache        = Collections.emptyMap();
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  null );
+    }
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator,
+                                  String parameterText) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  parameterText );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public Evaluator getEvaluator(final ValueType type,
+                                  final String operatorId,
+                                  final boolean isNegated,
+                                  final String parameterText) {
+        if ( this.cache == Collections.EMPTY_MAP ) {
+            this.cache = new HashMap<String, OverlapsEvaluator>();
+        }
+        String key = isNegated + ":" + parameterText;
+        OverlapsEvaluator eval = this.cache.get( key );
+        if ( eval == null ) {
+            eval = new OverlapsEvaluator( type,
+                                       isNegated,
+                                       parameterText );
+            this.cache.put( key,
+                            eval );
+        }
+        return eval;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public String[] getEvaluatorIds() {
+        return SUPPORTED_IDS;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean isNegatable() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean operatesOnFactHandles() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean supportsType(ValueType type) {
+        // supports all types, since it operates over fact handles
+        // Note: should we change this interface to allow checking of event classes only?
+        return true;
+    }
+
+    /**
+     * Implements the 'overlaps' evaluator itself
+     */
+    public static class OverlapsEvaluator extends BaseEvaluator {
+		private static final long serialVersionUID = -5108524288774833244L;
+		
+		private long                  startMinDev, startMaxDev;
+        private long                  endMinDev, endMaxDev;
+
+        public OverlapsEvaluator(final ValueType type,
+                              final boolean isNegated,
+                              final String parameters) {
+            super( type,
+                   isNegated ? OVERLAPS_NOT : OVERLAPS );
+            this.parseParameters( parameters );
+        }
+        
+        @Override
+        public Object prepareObject(InternalFactHandle handle) {
+            return handle;
+        }
+        
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            throw new RuntimeDroolsException( "The 'overlaps' operator can only be used to compare one event to another, and never to compare to literal constraints." );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                final VariableContextEntry context,
+                final Object left) {
+			
+        	if ( context.rightNull ) {
+        		return false;
+				}
+        	long leftStartTS = ((EventFactHandle) left ).getStartTimestamp();
+			long rightEndTS = ((EventFactHandle)((ObjectVariableContextEntry) context).right).getEndTimestamp();
+			long distStart = leftStartTS - ((EventFactHandle)((ObjectVariableContextEntry) context).right).getStartTimestamp();
+			long distEnd = ((EventFactHandle) left ).getEndTimestamp()- rightEndTS;
+			return this.getOperator().isNegated() ^ ( distStart >= this.startMinDev && distStart <= this.startMaxDev 
+					&& distEnd >= this.endMinDev && distEnd <= this.endMaxDev && leftStartTS < rightEndTS );
+		}
+			
+		public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+			               final VariableContextEntry context,
+			               final Object right) {
+			if ( context.extractor.isNullValue( workingMemory,
+			                     right ) ) {
+			return false;
+			}
+			long leftStartTS = ((EventFactHandle) ((ObjectVariableContextEntry) context).left).getStartTimestamp();
+			long rightEndTS = ((EventFactHandle) right ).getEndTimestamp();
+			long distStart = leftStartTS - ((EventFactHandle) right ).getStartTimestamp();
+			long distEnd = ((EventFactHandle) ((ObjectVariableContextEntry) context).left).getEndTimestamp() - rightEndTS;
+			return this.getOperator().isNegated() ^ ( distStart >= this.startMinDev && distStart <= this.startMaxDev 
+					&& distEnd >= this.endMinDev && distEnd <= this.endMaxDev && leftStartTS < rightEndTS );
+		}
+			
+		public boolean evaluate(InternalWorkingMemory workingMemory,
+			     final Extractor extractor1,
+			     final Object object1,
+			     final Extractor extractor2,
+			     final Object object2) {
+			if ( extractor1.isNullValue( workingMemory,
+			              object1 ) ) {
+			return false;
+			}
+			long o2startTS = ((EventFactHandle) object2 ).getStartTimestamp();
+			long o1endTS = ((EventFactHandle) object1 ).getEndTimestamp();
+			long distStart = o2startTS - ((EventFactHandle) object1 ).getStartTimestamp();
+			long distEnd = ((EventFactHandle) object2 ).getEndTimestamp() - o1endTS;
+			return this.getOperator().isNegated() ^ ( distStart >= this.startMinDev && distStart <= this.startMaxDev 
+					&& distEnd >= this.endMinDev && distEnd <= this.endMaxDev && o2startTS < o1endTS );
+		}
+
+        public String toString() {
+            return "overlaps[" + startMinDev + ", " + startMaxDev + ", " + endMinDev + ", " + endMaxDev + "]";
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int PRIME = 31;
+            int result = super.hashCode();
+            result = PRIME * result + (int) (endMaxDev ^ (endMaxDev >>> 32));
+            result = PRIME * result + (int) (endMinDev ^ (endMinDev >>> 32));
+            result = PRIME * result + (int) (startMaxDev ^ (startMaxDev >>> 32));
+            result = PRIME * result + (int) (startMinDev ^ (startMinDev >>> 32));
+            return result;
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#equals(java.lang.Object)
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if ( this == obj ) return true;
+            if ( !super.equals( obj ) ) return false;
+            if ( getClass() != obj.getClass() ) return false;
+            final OverlapsEvaluator other = (OverlapsEvaluator) obj;
+            return endMaxDev == other.endMaxDev && endMinDev == other.endMinDev
+            	&& startMaxDev == other.startMaxDev && startMinDev == other.startMinDev;
+        }
+
+        /**
+         * This methods tries to parse the string of parameters to customize 
+         * the evaluator.
+         * 
+         * @param parameters
+         */
+        private void parseParameters(String parameters) {
+            if ( parameters == null || parameters.trim().length() == 0 ) {
+                // open bounded ranges
+                this.startMinDev = 1;
+                this.startMaxDev = Long.MAX_VALUE;
+                this.endMinDev = 1;
+                this.endMaxDev = Long.MAX_VALUE;
+                return;
+            }
+
+            try {
+                String[] ranges = parameters.split( "," );
+                if ( ranges.length == 1 ) {
+                    // deterministic point in time for deviation of the starts of the intervals 
+                    this.startMinDev = Long.parseLong( ranges[0] );
+                    this.startMaxDev = this.startMinDev;
+                    this.endMinDev = this.startMinDev;
+                    this.endMaxDev = this.startMinDev;
+                } else if ( ranges.length == 2 ) {
+                    // deterministic points in time for deviations of the starts and the ends of the intervals 
+                    this.startMinDev = Long.parseLong( ranges[0] );
+                    this.startMaxDev = this.startMinDev;
+                    this.endMinDev = Long.parseLong( ranges[1] );
+                    this.endMaxDev = this.endMinDev;
+                } else if ( ranges.length == 4 ) {
+                    // ranges for deviations of the starts and the ends of the intervals 
+                	this.startMinDev = Long.parseLong( ranges[0] );
+                    this.startMaxDev = Long.parseLong( ranges[1] );
+                    this.endMinDev = Long.parseLong( ranges[2] );
+                    this.endMaxDev = Long.parseLong( ranges[3] );
+                } else {
+                    throw new RuntimeDroolsException( "[Overlaps Evaluator]: Not possible to parse parameters: '" + parameters + "'" );
+                }
+            } catch ( NumberFormatException e ) {
+                throw new RuntimeDroolsException( "[Overlaps Evaluator]: Not possible to parse parameters: '" + parameters + "'",
+                                                  e );
+            }
+        }
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/SetEvaluatorsDefinition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/SetEvaluatorsDefinition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/SetEvaluatorsDefinition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,1108 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 6, 2007
+ */
+package org.drools.base.evaluators;
+
+import java.util.Collection;
+
+import org.drools.base.BaseEvaluator;
+import org.drools.base.ValueType;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.VariableRestriction.ObjectVariableContextEntry;
+import org.drools.rule.VariableRestriction.VariableContextEntry;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldValue;
+import org.drools.util.ShadowProxyUtils;
+
+/**
+ * This class defines all the set built in 
+ * evaluators like contains, memberOf, etc.
+ * 
+ * @author etirelli
+ */
+public class SetEvaluatorsDefinition
+    implements
+    EvaluatorDefinition {
+
+    public static final Operator  CONTAINS      = Operator.addOperatorToRegistry( "contains",
+                                                                                  false );
+    public static final Operator  NOT_CONTAINS  = Operator.addOperatorToRegistry( "contains",
+                                                                                  true );
+    public static final Operator  EXCLUDES      = Operator.addOperatorToRegistry( "excludes",
+                                                                                  false );
+    public static final Operator  NOT_EXCLUDES  = Operator.addOperatorToRegistry( "excludes",
+                                                                                  true );
+    public static final Operator  MEMBEROF      = Operator.addOperatorToRegistry( "memberOf",
+                                                                                  false );
+    public static final Operator  NOT_MEMBEROF  = Operator.addOperatorToRegistry( "memberOf",
+                                                                                  true );
+
+    private static final String[] SUPPORTED_IDS = {CONTAINS.getOperatorString(), EXCLUDES.getOperatorString(), MEMBEROF.getOperatorString()};
+    private EvaluatorCache     evaluators    = new EvaluatorCache() {
+        private static final long serialVersionUID = 4782368623L;
+        {
+            addEvaluator( ValueType.ARRAY_TYPE,                          CONTAINS,                          ArrayContainsEvaluator.INSTANCE );
+            addEvaluator( ValueType.ARRAY_TYPE,                          NOT_CONTAINS,                      ArrayExcludesEvaluator.INSTANCE );
+            addEvaluator( ValueType.ARRAY_TYPE,                          EXCLUDES,                          ArrayExcludesEvaluator.INSTANCE );
+            addEvaluator( ValueType.ARRAY_TYPE,                          NOT_EXCLUDES,                      ArrayContainsEvaluator.INSTANCE );
+            addEvaluator( ValueType.ARRAY_TYPE,                          MEMBEROF,                          ArrayMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.ARRAY_TYPE,                          NOT_MEMBEROF,                      ArrayNotMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.BIG_DECIMAL_TYPE,                    MEMBEROF,                          BigDecimalMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.BIG_DECIMAL_TYPE,                    NOT_MEMBEROF,                      BigDecimalNotMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.BIG_INTEGER_TYPE,                    MEMBEROF,                          BigIntegerMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.BIG_INTEGER_TYPE,                    NOT_MEMBEROF,                      BigIntegerNotMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.BOOLEAN_TYPE,                        MEMBEROF,                          BooleanMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.BOOLEAN_TYPE,                        NOT_MEMBEROF,                      BooleanNotMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.PBOOLEAN_TYPE,                       MEMBEROF,                          BooleanMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.PBOOLEAN_TYPE,                       NOT_MEMBEROF,                      BooleanNotMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.BYTE_TYPE,                           MEMBEROF,                          ByteMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.BYTE_TYPE,                           NOT_MEMBEROF,                      ByteNotMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.PBYTE_TYPE,                          MEMBEROF,                          ByteMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.PBYTE_TYPE,                          NOT_MEMBEROF,                      ByteNotMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.CHAR_TYPE,                           MEMBEROF,                          CharacterMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.CHAR_TYPE,                           NOT_MEMBEROF,                      CharacterNotMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.PCHAR_TYPE,                          MEMBEROF,                          CharacterMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.PCHAR_TYPE,                          NOT_MEMBEROF,                      CharacterNotMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.DATE_TYPE,                           MEMBEROF,                          DateMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.DATE_TYPE,                           NOT_MEMBEROF,                      DateNotMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.DOUBLE_TYPE,                         MEMBEROF,                          DoubleMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.DOUBLE_TYPE,                         NOT_MEMBEROF,                      DoubleNotMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.PDOUBLE_TYPE,                        MEMBEROF,                          DoubleMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.PDOUBLE_TYPE,                        NOT_MEMBEROF,                      DoubleNotMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.FLOAT_TYPE,                          MEMBEROF,                          FloatMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.FLOAT_TYPE,                          NOT_MEMBEROF,                      FloatNotMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.PFLOAT_TYPE,                         MEMBEROF,                          FloatMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.PFLOAT_TYPE,                         NOT_MEMBEROF,                      FloatNotMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.INTEGER_TYPE,                        MEMBEROF,                          IntegerMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.INTEGER_TYPE,                        NOT_MEMBEROF,                      IntegerNotMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.PINTEGER_TYPE,                       MEMBEROF,                          IntegerMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.PINTEGER_TYPE,                       NOT_MEMBEROF,                      IntegerNotMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.LONG_TYPE,                           MEMBEROF,                          LongMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.LONG_TYPE,                           NOT_MEMBEROF,                      LongNotMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.PLONG_TYPE,                          MEMBEROF,                          LongMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.PLONG_TYPE,                          NOT_MEMBEROF,                      LongNotMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.OBJECT_TYPE,                         CONTAINS,                          ObjectContainsEvaluator.INSTANCE );
+            addEvaluator( ValueType.OBJECT_TYPE,                         NOT_CONTAINS,                      ObjectExcludesEvaluator.INSTANCE );
+            addEvaluator( ValueType.OBJECT_TYPE,                         EXCLUDES,                          ObjectExcludesEvaluator.INSTANCE );
+            addEvaluator( ValueType.OBJECT_TYPE,                         NOT_EXCLUDES,                      ObjectContainsEvaluator.INSTANCE );
+            addEvaluator( ValueType.OBJECT_TYPE,                         MEMBEROF,                          ObjectMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.OBJECT_TYPE,                         NOT_MEMBEROF,                      ObjectNotMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.SHORT_TYPE,                          MEMBEROF,                          ShortMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.SHORT_TYPE,                          NOT_MEMBEROF,                      ShortNotMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.PSHORT_TYPE,                         MEMBEROF,                          ShortMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.PSHORT_TYPE,                         NOT_MEMBEROF,                      ShortNotMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.STRING_TYPE,                         MEMBEROF,                          StringMemberOfEvaluator.INSTANCE );
+            addEvaluator( ValueType.STRING_TYPE,                         NOT_MEMBEROF,                      StringNotMemberOfEvaluator.INSTANCE );
+        }
+    };
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator) {
+        return this.evaluators.getEvaluator( type,
+                                             operator );
+    }
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator,
+                                  String parameterText) {
+        return this.evaluators.getEvaluator( type,
+                                             operator );
+    }
+
+    public Evaluator getEvaluator(final ValueType type,
+                                  final String operatorId,
+                                  final boolean isNegated,
+                                  final String parameterText) {
+        return this.evaluators.getEvaluator( type,
+                                             Operator.determineOperator( operatorId,
+                                                                         isNegated ) );
+    }
+
+    public String[] getEvaluatorIds() {
+        return SUPPORTED_IDS;
+    }
+
+    public boolean isNegatable() {
+        return true;
+    }
+
+    public boolean operatesOnFactHandles() {
+        return false;
+    }
+
+    public boolean supportsType(ValueType type) {
+        return this.evaluators.supportsType( type );
+    }
+
+    /*  *********************************************************
+     *                Evaluator Implementations
+     *  ********************************************************* 
+     */
+    static class ArrayContainsEvaluator extends BaseEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ArrayContainsEvaluator();
+
+        private ArrayContainsEvaluator() {
+            super( ValueType.ARRAY_TYPE,
+                   CONTAINS );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            final Object value = object2.getValue();
+            final Object[] array = (Object[]) extractor.getValue( workingMemory,
+                                                                  object1 );
+            if ( array == null ) return false;
+            return ShadowProxyUtils.contains( array,
+                                              value );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context,
+                                           final Object left) {
+            final Object value = context.declaration.getExtractor().getValue( workingMemory,
+                                                                              left );
+            final Object[] array = (Object[]) ((ObjectVariableContextEntry) context).right;
+            if ( array == null ) return false;
+            return ShadowProxyUtils.contains( array,
+                                              value );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context,
+                                          final Object right) {
+            final Object value = ((ObjectVariableContextEntry) context).left;
+            final Object[] array = (Object[]) context.extractor.getValue( workingMemory,
+                                                                          right );
+            if ( array == null ) return false;
+            return ShadowProxyUtils.contains( array,
+                                              value );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2,
+                                final Object object2) {
+            final Object value = extractor2.getValue( workingMemory,
+                                                      object2 );
+            final Object[] array = (Object[]) extractor1.getValue( workingMemory,
+                                                                   object1 );
+
+            if ( array == null ) return false;
+            return ShadowProxyUtils.contains( array,
+                                              value );
+        }
+
+        public String toString() {
+            return "Array contains";
+        }
+    }
+
+    static class ArrayExcludesEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ArrayExcludesEvaluator();
+
+        private ArrayExcludesEvaluator() {
+            super( ValueType.ARRAY_TYPE,
+                   EXCLUDES );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            final Object value = object2.getValue();
+            final Object[] array = (Object[]) extractor.getValue( workingMemory,
+                                                                  object1 );
+            if ( array == null ) return true;
+            return !ShadowProxyUtils.contains( array,
+                                               value );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context,
+                                           final Object left) {
+            final Object value = context.declaration.getExtractor().getValue( workingMemory,
+                                                                              left );
+            final Object[] array = (Object[]) ((ObjectVariableContextEntry) context).right;
+            if ( array == null ) return true;
+            return !ShadowProxyUtils.contains( array,
+                                               value );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context,
+                                          final Object right) {
+            final Object value = ((ObjectVariableContextEntry) context).left;
+            final Object[] array = (Object[]) context.extractor.getValue( workingMemory,
+                                                                          right );
+            if ( array == null ) return true;
+            return !ShadowProxyUtils.contains( array,
+                                               value );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2,
+                                final Object object2) {
+            final Object value = extractor2.getValue( workingMemory,
+                                                      object2 );
+            final Object[] array = (Object[]) extractor1.getValue( workingMemory,
+                                                                   object1 );
+
+            if ( array == null ) return true;
+            return !ShadowProxyUtils.contains( array,
+                                               value );
+        }
+
+        public String toString() {
+            return "Array excludes";
+        }
+    }
+
+    static class ArrayMemberOfEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ArrayMemberOfEvaluator();
+
+        private ArrayMemberOfEvaluator() {
+            super( ValueType.ARRAY_TYPE,
+                   MEMBEROF );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            final Object[] array = (Object[]) object2.getValue();
+            final Object value = extractor.getValue( workingMemory,
+                                                     object1 );
+            if ( array == null ) return false;
+            return ShadowProxyUtils.contains( array,
+                                              value );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context,
+                                           final Object left) {
+            final Object[] array = (Object[]) context.declaration.getExtractor().getValue( workingMemory,
+                                                                                           left );
+            final Object value = ((ObjectVariableContextEntry) context).right;
+            if ( array == null ) return false;
+            return ShadowProxyUtils.contains( array,
+                                              value );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context,
+                                          final Object right) {
+            final Object[] array = (Object[]) ((ObjectVariableContextEntry) context).left;
+            final Object value = context.extractor.getValue( workingMemory,
+                                                             right );
+            if ( array == null ) return false;
+            return ShadowProxyUtils.contains( array,
+                                              value );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2,
+                                final Object object2) {
+            final Object[] array = (Object[]) extractor2.getValue( workingMemory,
+                                                                   object2 );
+            final Object value = extractor1.getValue( workingMemory,
+                                                      object1 );
+
+            if ( array == null ) return false;
+            return ShadowProxyUtils.contains( array,
+                                              value );
+        }
+
+        public String toString() {
+            return "Array memberOf";
+        }
+    }
+
+    static class ArrayNotMemberOfEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ArrayNotMemberOfEvaluator();
+
+        private ArrayNotMemberOfEvaluator() {
+            super( ValueType.ARRAY_TYPE,
+                   NOT_MEMBEROF );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            final Object[] array = (Object[]) object2.getValue();
+            final Object value = extractor.getValue( workingMemory,
+                                                     object1 );
+            if ( array == null ) return true;
+            return !ShadowProxyUtils.contains( array,
+                                               value );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context,
+                                           final Object left) {
+            final Object[] array = (Object[]) context.declaration.getExtractor().getValue( workingMemory,
+                                                                                           left );
+            final Object value = ((ObjectVariableContextEntry) context).right;
+            if ( array == null ) return true;
+            return !ShadowProxyUtils.contains( array,
+                                               value );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context,
+                                          final Object right) {
+            final Object[] array = (Object[]) ((ObjectVariableContextEntry) context).left;
+            final Object value = context.extractor.getValue( workingMemory,
+                                                             right );
+            if ( array == null ) return true;
+            return !ShadowProxyUtils.contains( array,
+                                               value );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2,
+                                final Object object2) {
+            final Object[] array = (Object[]) extractor2.getValue( workingMemory,
+                                                                   object2 );
+            final Object value = extractor1.getValue( workingMemory,
+                                                      object1 );
+
+            if ( array == null ) return true;
+            return !ShadowProxyUtils.contains( array,
+                                               value );
+        }
+
+        public String toString() {
+            return "Array not memberOf";
+        }
+    }
+
+    static abstract class BaseMemberOfEvaluator extends BaseEvaluator {
+
+        private static final long serialVersionUID = 2017803222427893249L;
+
+        public BaseMemberOfEvaluator(ValueType type,
+                                     Operator operator) {
+            super( type,
+                   operator );
+        }
+
+        public ValueType getCoercedValueType() {
+            // during evaluation, always coerce to object
+            return ValueType.OBJECT_TYPE;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            if ( object2.isNull() ) {
+                return false;
+            } else if ( !object2.isCollectionField() ) {
+                throw new ClassCastException( "Can't check if an attribute is member of an object of class " + object2.getValue().getClass() );
+            }
+            final Collection col = (Collection) object2.getValue();
+            final Object value = extractor.getValue( workingMemory,
+                                                     object1 );
+            return ShadowProxyUtils.contains( col,
+                                              value );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context,
+                                           final Object left) {
+            final Object object = context.declaration.getExtractor().getValue( workingMemory,
+                                                                               left );
+            if ( object == null ) {
+                return false;
+            } else if ( !(object instanceof Collection) ) {
+                throw new ClassCastException( "Can't check if an attribute is member of an object of class " + object.getClass() );
+            }
+            final Collection col = (Collection) object;
+            final Object value = ((ObjectVariableContextEntry) context).right;
+            return ShadowProxyUtils.contains( col,
+                                              value );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context,
+                                          final Object right) {
+            final Object object = ((ObjectVariableContextEntry) context).left;
+            if ( object == null ) {
+                return false;
+            } else if ( !(object instanceof Collection) ) {
+                throw new ClassCastException( "Can't check if an attribute is member of an object of class " + object.getClass() );
+            }
+            final Collection col = (Collection) object;
+            final Object value = context.extractor.getValue( workingMemory,
+                                                             right );
+            return ShadowProxyUtils.contains( col,
+                                              value );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2,
+                                final Object object2) {
+            final Object object = extractor2.getValue( workingMemory,
+                                                       object2 );
+            if ( object == null ) {
+                return false;
+            } else if ( !(object instanceof Collection) ) {
+                throw new ClassCastException( "Can't check if an attribute is member of an object of class " + object.getClass() );
+            }
+            final Collection col = (Collection) object;
+            final Object value = extractor1.getValue( workingMemory,
+                                                      object1 );
+            return ShadowProxyUtils.contains( col,
+                                              value );
+        }
+
+        public abstract String toString();
+
+    }
+
+    static abstract class BaseNotMemberOfEvaluator extends BaseEvaluator {
+
+        private static final long serialVersionUID = -8730331781980886901L;
+
+        public BaseNotMemberOfEvaluator(ValueType type,
+                                        Operator operator) {
+            super( type,
+                   operator );
+        }
+
+        public ValueType getCoercedValueType() {
+            // during evaluation, always coerce to object
+            return ValueType.OBJECT_TYPE;
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            if ( object2.isNull() ) {
+                return false;
+            } else if ( !object2.isCollectionField() ) {
+                throw new ClassCastException( "Can't check if an attribute is not member of an object of class " + object2.getValue().getClass() );
+            }
+            final Collection col = (Collection) object2.getValue();
+            final Object value = extractor.getValue( workingMemory,
+                                                     object1 );
+            return !ShadowProxyUtils.contains( col,
+                                               value );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context,
+                                           final Object left) {
+            final Object object = context.declaration.getExtractor().getValue( workingMemory,
+                                                                               left );
+            if ( object == null ) {
+                return false;
+            } else if ( !(object instanceof Collection) ) {
+                throw new ClassCastException( "Can't check if an attribute is not member of an object of class " + object.getClass() );
+            }
+            final Collection col = (Collection) object;
+            final Object value = ((ObjectVariableContextEntry) context).right;
+            return !ShadowProxyUtils.contains( col,
+                                               value );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context,
+                                          final Object right) {
+            final Object object = ((ObjectVariableContextEntry) context).left;
+            if ( object == null ) {
+                return false;
+            } else if ( !(object instanceof Collection) ) {
+                throw new ClassCastException( "Can't check if an attribute is not member of an object of class " + object.getClass() );
+            }
+            final Collection col = (Collection) object;
+            final Object value = context.extractor.getValue( workingMemory,
+                                                             right );
+            return !ShadowProxyUtils.contains( col,
+                                               value );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2,
+                                final Object object2) {
+            final Object object = extractor2.getValue( workingMemory,
+                                                       object2 );
+            if ( object == null ) {
+                return false;
+            } else if ( !(object instanceof Collection) ) {
+                throw new ClassCastException( "Can't check if an attribute is not member of an object of class " + object.getClass() );
+            }
+            final Collection col = (Collection) object;
+            final Object value = extractor1.getValue( workingMemory,
+                                                      object1 );
+            return !ShadowProxyUtils.contains( col,
+                                               value );
+        }
+
+        public abstract String toString();
+    }
+
+    static class BigDecimalMemberOfEvaluator extends BaseMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new BigDecimalMemberOfEvaluator();
+
+        private BigDecimalMemberOfEvaluator() {
+            super( ValueType.BIG_DECIMAL_TYPE,
+                   MEMBEROF );
+        }
+
+        public String toString() {
+            return "BigDecimal memberOf";
+        }
+    }
+
+    static class BigDecimalNotMemberOfEvaluator extends BaseNotMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new BigDecimalNotMemberOfEvaluator();
+
+        private BigDecimalNotMemberOfEvaluator() {
+            super( ValueType.BIG_DECIMAL_TYPE,
+                   NOT_MEMBEROF );
+        }
+
+        public String toString() {
+            return "BigDecimal not memberOf";
+        }
+    }
+
+    static class BigIntegerMemberOfEvaluator extends BaseMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new BigIntegerMemberOfEvaluator();
+
+        private BigIntegerMemberOfEvaluator() {
+            super( ValueType.BIG_INTEGER_TYPE,
+                   MEMBEROF );
+        }
+
+        public String toString() {
+            return "BigInteger memberOf";
+        }
+    }
+
+    static class BigIntegerNotMemberOfEvaluator extends BaseNotMemberOfEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new BigIntegerNotMemberOfEvaluator();
+
+        private BigIntegerNotMemberOfEvaluator() {
+            super( ValueType.BIG_INTEGER_TYPE,
+                   NOT_MEMBEROF );
+        }
+
+        public String toString() {
+            return "BigInteger not memberOf";
+        }
+    }
+
+    static class BooleanMemberOfEvaluator extends BaseMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new BooleanMemberOfEvaluator();
+
+        private BooleanMemberOfEvaluator() {
+            super( ValueType.PBOOLEAN_TYPE,
+                   MEMBEROF );
+        }
+
+        public String toString() {
+            return "Boolean memberOf";
+        }
+    }
+
+    static class BooleanNotMemberOfEvaluator extends BaseNotMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new BooleanNotMemberOfEvaluator();
+
+        private BooleanNotMemberOfEvaluator() {
+            super( ValueType.PBOOLEAN_TYPE,
+                   NOT_MEMBEROF );
+        }
+
+        public String toString() {
+            return "Boolean not memberOf";
+        }
+    }
+
+    static class ByteMemberOfEvaluator extends BaseMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ByteMemberOfEvaluator();
+
+        private ByteMemberOfEvaluator() {
+            super( ValueType.PBYTE_TYPE,
+                   MEMBEROF );
+        }
+
+        public String toString() {
+            return "Byte memberOf";
+        }
+    }
+
+    static class ByteNotMemberOfEvaluator extends BaseNotMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ByteNotMemberOfEvaluator();
+
+        private ByteNotMemberOfEvaluator() {
+            super( ValueType.PBYTE_TYPE,
+                   NOT_MEMBEROF );
+        }
+
+        public String toString() {
+            return "Byte not memberOf";
+        }
+    }
+
+    static class CharacterMemberOfEvaluator extends BaseMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new CharacterMemberOfEvaluator();
+
+        private CharacterMemberOfEvaluator() {
+            super( ValueType.PCHAR_TYPE,
+                   MEMBEROF );
+        }
+
+        public String toString() {
+            return "Character memberOf";
+        }
+    }
+
+    static class CharacterNotMemberOfEvaluator extends BaseNotMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new CharacterNotMemberOfEvaluator();
+
+        private CharacterNotMemberOfEvaluator() {
+            super( ValueType.PCHAR_TYPE,
+                   NOT_MEMBEROF );
+        }
+
+        public String toString() {
+            return "Character not memberOf";
+        }
+    }
+
+    static class DateMemberOfEvaluator extends BaseMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new DateMemberOfEvaluator();
+
+        private DateMemberOfEvaluator() {
+            super( ValueType.DATE_TYPE,
+                   MEMBEROF );
+        }
+
+        public String toString() {
+            return "Date memberOf";
+        }
+    }
+
+    static class DateNotMemberOfEvaluator extends BaseNotMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new DateNotMemberOfEvaluator();
+
+        private DateNotMemberOfEvaluator() {
+            super( ValueType.DATE_TYPE,
+                   NOT_MEMBEROF );
+        }
+
+        public String toString() {
+            return "Date not memberOf";
+        }
+    }
+
+    static class DoubleMemberOfEvaluator extends BaseMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new DoubleMemberOfEvaluator();
+
+        private DoubleMemberOfEvaluator() {
+            super( ValueType.PDOUBLE_TYPE,
+                   MEMBEROF );
+        }
+
+        public String toString() {
+            return "Double memberOf";
+        }
+    }
+
+    static class DoubleNotMemberOfEvaluator extends BaseNotMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new DoubleNotMemberOfEvaluator();
+
+        private DoubleNotMemberOfEvaluator() {
+            super( ValueType.PDOUBLE_TYPE,
+                   NOT_MEMBEROF );
+        }
+
+        public String toString() {
+            return "Double not memberOf";
+        }
+    }
+
+    static class FloatMemberOfEvaluator extends BaseMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new FloatMemberOfEvaluator();
+
+        private FloatMemberOfEvaluator() {
+            super( ValueType.PFLOAT_TYPE,
+                   MEMBEROF );
+        }
+
+        public String toString() {
+            return "Float memberOf";
+        }
+    }
+
+    static class FloatNotMemberOfEvaluator extends BaseNotMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new FloatNotMemberOfEvaluator();
+
+        private FloatNotMemberOfEvaluator() {
+            super( ValueType.PFLOAT_TYPE,
+                   NOT_MEMBEROF );
+        }
+
+        public String toString() {
+            return "Float not memberOf";
+        }
+    }
+
+    static class IntegerMemberOfEvaluator extends BaseMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new IntegerMemberOfEvaluator();
+
+        private IntegerMemberOfEvaluator() {
+            super( ValueType.PINTEGER_TYPE,
+                   MEMBEROF );
+        }
+
+        public String toString() {
+            return "Integer memberOf";
+        }
+    }
+
+    static class IntegerNotMemberOfEvaluator extends BaseNotMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new IntegerNotMemberOfEvaluator();
+
+        private IntegerNotMemberOfEvaluator() {
+            super( ValueType.PINTEGER_TYPE,
+                   NOT_MEMBEROF );
+        }
+
+        public String toString() {
+            return "Integer not memberOf";
+        }
+    }
+
+    static class LongMemberOfEvaluator extends BaseMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new LongMemberOfEvaluator();
+
+        private LongMemberOfEvaluator() {
+            super( ValueType.PLONG_TYPE,
+                   MEMBEROF );
+        }
+
+        public String toString() {
+            return "Long memberOf";
+        }
+    }
+
+    static class LongNotMemberOfEvaluator extends BaseNotMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new LongNotMemberOfEvaluator();
+
+        private LongNotMemberOfEvaluator() {
+            super( ValueType.PLONG_TYPE,
+                   NOT_MEMBEROF );
+        }
+
+        public String toString() {
+            return "Long not memberOf";
+        }
+    }
+
+    static class ObjectContainsEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ObjectContainsEvaluator();
+
+        private ObjectContainsEvaluator() {
+            super( ValueType.OBJECT_TYPE,
+                   CONTAINS );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            final Object value = object2.getValue();
+            final Collection col = (Collection) extractor.getValue( workingMemory,
+                                                                    object1 );
+            return (col == null) ? false : ShadowProxyUtils.contains( col,
+                                                                      value );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context,
+                                           final Object left) {
+            final Object value = context.declaration.getExtractor().getValue( workingMemory,
+                                                                              left );
+            final Collection col = (Collection) ((ObjectVariableContextEntry) context).right;
+            return (col == null) ? false : ShadowProxyUtils.contains( col,
+                                                                      value );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context,
+                                          final Object right) {
+            final Object value = ((ObjectVariableContextEntry) context).left;
+            final Collection col = (Collection) context.extractor.getValue( workingMemory,
+                                                                            right );
+            return (col == null) ? false : ShadowProxyUtils.contains( col,
+                                                                      value );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2,
+                                final Object object2) {
+            final Object value = extractor2.getValue( workingMemory,
+                                                      object2 );
+            final Collection col = (Collection) extractor1.getValue( workingMemory,
+                                                                     object1 );
+            return (col == null) ? false : ShadowProxyUtils.contains( col,
+                                                                      value );
+        }
+
+        public String toString() {
+            return "Object contains";
+        }
+    }
+
+    static class ObjectExcludesEvaluator extends BaseEvaluator {
+        /**
+         * 
+         */
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ObjectExcludesEvaluator();
+
+        private ObjectExcludesEvaluator() {
+            super( ValueType.OBJECT_TYPE,
+                   EXCLUDES );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            final Object value = object2.getValue();
+            final Collection col = (Collection) extractor.getValue( workingMemory,
+                                                                    object1 );
+            return (col == null) ? true : !ShadowProxyUtils.contains( col,
+                                                                      value );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context,
+                                           final Object left) {
+            final Object value = context.declaration.getExtractor().getValue( workingMemory,
+                                                                              left );
+            final Collection col = (Collection) ((ObjectVariableContextEntry) context).right;
+            return (col == null) ? true : !ShadowProxyUtils.contains( col,
+                                                                      value );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context,
+                                          final Object right) {
+            final Object value = ((ObjectVariableContextEntry) context).left;
+            final Collection col = (Collection) context.extractor.getValue( workingMemory,
+                                                                            right );
+            return (col == null) ? true : !ShadowProxyUtils.contains( col,
+                                                                      value );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2,
+                                final Object object2) {
+            final Object value = extractor2.getValue( workingMemory,
+                                                      object2 );
+            final Collection col = (Collection) extractor1.getValue( workingMemory,
+                                                                     object1 );
+            return (col == null) ? true : !ShadowProxyUtils.contains( col,
+                                                                      value );
+        }
+
+        public String toString() {
+            return "Object excludes";
+        }
+    }
+
+    static class ObjectMemberOfEvaluator extends BaseMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ObjectMemberOfEvaluator();
+
+        private ObjectMemberOfEvaluator() {
+            super( ValueType.OBJECT_TYPE,
+                   MEMBEROF );
+        }
+
+        public String toString() {
+            return "Object memberOf";
+        }
+    }
+
+    static class ObjectNotMemberOfEvaluator extends BaseNotMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ObjectNotMemberOfEvaluator();
+
+        private ObjectNotMemberOfEvaluator() {
+            super( ValueType.OBJECT_TYPE,
+                   NOT_MEMBEROF );
+        }
+
+        public String toString() {
+            return "Object not memberOf";
+        }
+    }
+
+    static class ShortMemberOfEvaluator extends BaseMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ShortMemberOfEvaluator();
+
+        private ShortMemberOfEvaluator() {
+            super( ValueType.PSHORT_TYPE,
+                   MEMBEROF );
+        }
+
+        public String toString() {
+            return "Short memberOf";
+        }
+    }
+
+    static class ShortNotMemberOfEvaluator extends BaseNotMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new ShortNotMemberOfEvaluator();
+
+        private ShortNotMemberOfEvaluator() {
+            super( ValueType.PSHORT_TYPE,
+                   NOT_MEMBEROF );
+        }
+
+        public String toString() {
+            return "Short not memberOf";
+        }
+    }
+
+    static class StringMemberOfEvaluator extends BaseMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new StringMemberOfEvaluator();
+
+        private StringMemberOfEvaluator() {
+            super( ValueType.STRING_TYPE,
+                   MEMBEROF );
+        }
+
+        public String toString() {
+            return "String memberOf";
+        }
+    }
+
+    static class StringNotMemberOfEvaluator extends BaseNotMemberOfEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new StringNotMemberOfEvaluator();
+
+        private StringNotMemberOfEvaluator() {
+            super( ValueType.STRING_TYPE,
+                   NOT_MEMBEROF );
+        }
+
+        public String toString() {
+            return "String not memberOf";
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/SoundslikeEvaluatorsDefinition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/SoundslikeEvaluatorsDefinition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/SoundslikeEvaluatorsDefinition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 6, 2007
+ */
+package org.drools.base.evaluators;
+
+import org.drools.base.BaseEvaluator;
+import org.drools.base.ValueType;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.VariableRestriction.ObjectVariableContextEntry;
+import org.drools.rule.VariableRestriction.VariableContextEntry;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldValue;
+import org.mvel.Soundex;
+
+/**
+ * This class defines the soundslike evaluator
+ * 
+ * @author etirelli
+ */
+public class SoundslikeEvaluatorsDefinition implements EvaluatorDefinition {
+    
+    public static final Operator  SOUNDSLIKE       = Operator.addOperatorToRegistry( "soundslike",
+                                                                                     false );
+    public static final Operator  NOT_SOUNDSLIKE   = Operator.addOperatorToRegistry( "soundslike",
+                                                                                     true );
+    
+    private static final String[] SUPPORTED_IDS = { SOUNDSLIKE.getOperatorString() };
+    private EvaluatorCache evaluators = new EvaluatorCache() {
+        private static final long serialVersionUID = 4782368623L;
+        {
+            addEvaluator( ValueType.STRING_TYPE,        SOUNDSLIKE,         StringSoundsLikeEvaluator.INSTANCE );
+            addEvaluator( ValueType.STRING_TYPE,        NOT_SOUNDSLIKE,     StringNotSoundsLikeEvaluator.INSTANCE );
+        }
+    };
+    
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator) {
+        return this.evaluators.getEvaluator( type,
+                                             operator );
+    }
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator,
+                                  String parameterText) {
+        return this.evaluators.getEvaluator( type,
+                                             operator );
+    }
+
+    public Evaluator getEvaluator(final ValueType type,
+                                  final String operatorId,
+                                  final boolean isNegated,
+                                  final String parameterText) {
+        return this.evaluators.getEvaluator( type, 
+                                             Operator.determineOperator( operatorId, 
+                                                                         isNegated ) );
+    }
+
+    public String[] getEvaluatorIds() {
+        return SUPPORTED_IDS;
+    }
+
+    public boolean isNegatable() {
+        return true;
+    }
+
+    public boolean operatesOnFactHandles() {
+        return false;
+    }
+
+    public boolean supportsType(ValueType type) {
+        return this.evaluators.supportsType( type );
+    }
+    
+    /*  *********************************************************
+     *           Evaluator Implementations
+     *  *********************************************************
+     */
+    static class StringSoundsLikeEvaluator extends BaseEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new StringSoundsLikeEvaluator();
+
+        private StringSoundsLikeEvaluator() {
+            super( ValueType.STRING_TYPE,
+                   SOUNDSLIKE );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            final String value1 = (String) extractor.getValue( workingMemory, object1 );
+            final String value2 = (String) object2.getValue();
+            if ( value1 == null ) {
+                return false;
+            }
+
+            return Soundex.soundex( value1 ).equals(  Soundex.soundex(value2) );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            final String value = (String) ((ObjectVariableContextEntry) context).right;
+            if ( value == null ) {
+                return false;
+            }
+            return Soundex.soundex( value ).equals( Soundex.soundex((String) context.declaration.getExtractor().getValue( workingMemory, left )) );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            final String value = (String) context.extractor.getValue( workingMemory, right );
+            if ( value == null ) {
+                return false;
+            }
+            return Soundex.soundex(value).equals( Soundex.soundex((String) ((ObjectVariableContextEntry) context).left ));
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            final Object value1 = extractor1.getValue( workingMemory, object1 );
+            final Object value2 = extractor2.getValue( workingMemory, object2 );
+            if ( value1 == null ) {
+                return false;
+            }
+            return Soundex.soundex( ((String) value1)).equals( Soundex.soundex( (String) value2 ));
+        }
+
+        public String toString() {
+            return "Strings sound alike";
+        }
+    }
+    
+    static class StringNotSoundsLikeEvaluator extends BaseEvaluator {
+
+        private static final long     serialVersionUID = 400L;
+        public final static Evaluator INSTANCE         = new StringNotSoundsLikeEvaluator();
+
+        private StringNotSoundsLikeEvaluator() {
+            super( ValueType.STRING_TYPE,
+                   NOT_SOUNDSLIKE );
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1, final FieldValue object2) {
+            final String value1 = (String) extractor.getValue( workingMemory, object1 );
+            final String value2 = (String) object2.getValue();
+            if ( value1 == null ) {
+                return false;
+            }
+
+            return ! Soundex.soundex( value1 ).equals(  Soundex.soundex(value2) );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                           final VariableContextEntry context, final Object left) {
+            final String value = (String) ((ObjectVariableContextEntry) context).right;
+            if ( value == null ) {
+                return false;
+            }
+            return ! Soundex.soundex( value ).equals( Soundex.soundex((String) context.declaration.getExtractor().getValue( workingMemory, left )) );
+        }
+
+        public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                          final VariableContextEntry context, final Object right) {
+            final String value = (String) context.extractor.getValue( workingMemory, right );
+            if ( value == null ) {
+                return false;
+            }
+            return ! Soundex.soundex(value).equals( Soundex.soundex((String) ((ObjectVariableContextEntry) context).left ));
+        }
+
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor1,
+                                final Object object1,
+                                final Extractor extractor2, final Object object2) {
+            final Object value1 = extractor1.getValue( workingMemory, object1 );
+            final Object value2 = extractor2.getValue( workingMemory, object2 );
+            if ( value1 == null ) {
+                return false;
+            }
+            return ! Soundex.soundex( ((String) value1)).equals( Soundex.soundex( (String) value2 ));
+        }
+
+        public String toString() {
+            return "Strings not sound alike";
+        }
+    }
+    
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/StartedByEvaluatorDefinition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/StartedByEvaluatorDefinition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/StartedByEvaluatorDefinition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,274 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 6, 2007
+ */
+package org.drools.base.evaluators;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.BaseEvaluator;
+import org.drools.base.ValueType;
+import org.drools.common.EventFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.VariableRestriction.ObjectVariableContextEntry;
+import org.drools.rule.VariableRestriction.VariableContextEntry;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldValue;
+
+/**
+ * The implementation of the 'startedby' evaluator definition
+ * 
+ * @author mgroch
+ */
+public class StartedByEvaluatorDefinition
+    implements
+    EvaluatorDefinition {
+
+    public static final Operator  STARTED_BY       = Operator.addOperatorToRegistry( "startedby",
+                                                                                  false );
+    public static final Operator  NOT_STARTED_BY   = Operator.addOperatorToRegistry( "startedby",
+                                                                                  true );
+    
+    private static final String[] SUPPORTED_IDS = { STARTED_BY.getOperatorString() };
+    
+    private Map<String, StartedByEvaluator> cache        = Collections.emptyMap();
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  null );
+    }
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator,
+                                  String parameterText) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  parameterText );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public Evaluator getEvaluator(final ValueType type,
+                                  final String operatorId,
+                                  final boolean isNegated,
+                                  final String parameterText) {
+        if ( this.cache == Collections.EMPTY_MAP ) {
+            this.cache = new HashMap<String, StartedByEvaluator>();
+        }
+        String key = isNegated + ":" + parameterText;
+        StartedByEvaluator eval = this.cache.get( key );
+        if ( eval == null ) {
+            eval = new StartedByEvaluator( type,
+                                       isNegated,
+                                       parameterText );
+            this.cache.put( key,
+                            eval );
+        }
+        return eval;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public String[] getEvaluatorIds() {
+        return SUPPORTED_IDS;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean isNegatable() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean operatesOnFactHandles() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean supportsType(ValueType type) {
+        // supports all types, since it operates over fact handles
+        // Note: should we change this interface to allow checking of event classes only?
+        return true;
+    }
+
+    /**
+     * Implements the 'startedby' evaluator itself
+     */
+    public static class StartedByEvaluator extends BaseEvaluator {
+		private static final long serialVersionUID = -2655549435451501420L;
+		
+		private long                  startDev;
+        private long                  endMinDev, endMaxDev;
+
+        public StartedByEvaluator(final ValueType type,
+                              final boolean isNegated,
+                              final String parameters) {
+            super( type,
+                   isNegated ? NOT_STARTED_BY : STARTED_BY );
+            this.parseParameters( parameters );
+        }
+        
+        @Override
+        public Object prepareObject(InternalFactHandle handle) {
+            return handle;
+        }
+        
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            throw new RuntimeDroolsException( "The 'startedby' operator can only be used to compare one event to another, and never to compare to literal constraints." );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                final VariableContextEntry context,
+                final Object left) {
+			
+        	if ( context.rightNull ) {
+        		return false;
+				}
+			long distStart = Math.abs(((EventFactHandle)((ObjectVariableContextEntry) context).right).getStartTimestamp() - ((EventFactHandle) left ).getStartTimestamp());
+			long distEnd = ((EventFactHandle)((ObjectVariableContextEntry) context).right).getEndTimestamp() - ((EventFactHandle) left ).getEndTimestamp();
+			return this.getOperator().isNegated() ^ ( distStart <= this.startDev 
+					&& distEnd >= this.endMinDev && distEnd <= this.endMaxDev );
+		}
+			
+		public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+			               final VariableContextEntry context,
+			               final Object right) {
+			if ( context.extractor.isNullValue( workingMemory,
+			                     right ) ) {
+			return false;
+			}
+			long distStart = Math.abs(((EventFactHandle) right ).getStartTimestamp() - ((EventFactHandle) ((ObjectVariableContextEntry) context).left).getStartTimestamp());
+			long distEnd = ((EventFactHandle) right ).getEndTimestamp() - ((EventFactHandle) ((ObjectVariableContextEntry) context).left).getEndTimestamp();
+			return this.getOperator().isNegated() ^ ( distStart <= this.startDev 
+					&& distEnd >= this.endMinDev && distEnd <= this.endMaxDev );
+		}
+			
+		public boolean evaluate(InternalWorkingMemory workingMemory,
+			     final Extractor extractor1,
+			     final Object object1,
+			     final Extractor extractor2,
+			     final Object object2) {
+			if ( extractor1.isNullValue( workingMemory,
+			              object1 ) ) {
+			return false;
+			}
+			long distStart = Math.abs(((EventFactHandle) object1 ).getStartTimestamp() - ((EventFactHandle) object2 ).getStartTimestamp());
+			long distEnd = ((EventFactHandle) object1 ).getEndTimestamp() - ((EventFactHandle) object2 ).getEndTimestamp();
+			return this.getOperator().isNegated() ^ ( distStart  <= this.startDev 
+					&& distEnd >= this.endMinDev && distEnd <= this.endMaxDev );
+		}
+
+        public String toString() {
+            return "startedby[" + startDev + ", " + endMinDev + ", " + endMaxDev + "]";
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int PRIME = 31;
+            int result = super.hashCode();
+            result = PRIME * result + (int) (endMaxDev ^ (endMaxDev >>> 32));
+            result = PRIME * result + (int) (endMinDev ^ (endMinDev >>> 32));
+            result = PRIME * result + (int) (startDev ^ (startDev >>> 32));
+            return result;
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#equals(java.lang.Object)
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if ( this == obj ) return true;
+            if ( !super.equals( obj ) ) return false;
+            if ( getClass() != obj.getClass() ) return false;
+            final StartedByEvaluator other = (StartedByEvaluator) obj;
+            return endMaxDev == other.endMaxDev && endMinDev == other.endMinDev && startDev == other.startDev;
+        }
+
+        /**
+         * This methods tries to parse the string of parameters to customize 
+         * the evaluator.
+         * 
+         * @param parameters
+         */
+        private void parseParameters(String parameters) {
+            if ( parameters == null || parameters.trim().length() == 0 ) {
+                // exact matching at the beginning of the intervals, open bounded ranges for the ends
+                this.startDev = 0;
+                this.endMinDev = 1;
+                this.endMaxDev = Long.MAX_VALUE;
+                return;
+            }
+
+            try {
+                String[] ranges = parameters.split( "," );
+                if ( ranges.length == 1 ) {
+                    // exact matching at the beginning of the intervals
+                	// deterministic point in time for deviations of the ends of the intervals
+                	this.startDev = 0;
+                	this.endMinDev = Long.parseLong( ranges[0] );
+                    this.endMaxDev = this.endMinDev;
+                } else if ( ranges.length == 2 ) {
+                    // exact matching at the beginning of the intervals
+                	// range for deviations of the ends of the intervals 
+                	this.startDev = 0;
+                    this.endMinDev = Long.parseLong( ranges[0] );
+                    this.endMaxDev = Long.parseLong( ranges[1] );
+                } else if ( ranges.length == 3 ) {
+                	// max. deviation at the starts of the intervals
+                	// range for deviations of the ends of the intervals 
+                	this.startDev = Long.parseLong( ranges[0] );;
+                    this.endMinDev = Long.parseLong( ranges[1] );
+                    this.endMaxDev = Long.parseLong( ranges[2] );
+                } else {
+                    throw new RuntimeDroolsException( "[StartedBy Evaluator]: Not possible to parse parameters: '" + parameters + "'" );
+                }
+            } catch ( NumberFormatException e ) {
+                throw new RuntimeDroolsException( "[StartedBy Evaluator]: Not possible to parse parameters: '" + parameters + "'",
+                                                  e );
+            }
+        }
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/StartsEvaluatorDefinition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/StartsEvaluatorDefinition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/evaluators/StartsEvaluatorDefinition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,274 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 6, 2007
+ */
+package org.drools.base.evaluators;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.BaseEvaluator;
+import org.drools.base.ValueType;
+import org.drools.common.EventFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.VariableRestriction.ObjectVariableContextEntry;
+import org.drools.rule.VariableRestriction.VariableContextEntry;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldValue;
+
+/**
+ * The implementation of the 'starts' evaluator definition
+ * 
+ * @author mgroch
+ */
+public class StartsEvaluatorDefinition
+    implements
+    EvaluatorDefinition {
+
+    public static final Operator  STARTS       = Operator.addOperatorToRegistry( "starts",
+                                                                                  false );
+    public static final Operator  STARTS_NOT   = Operator.addOperatorToRegistry( "starts",
+                                                                                  true );
+    
+    private static final String[] SUPPORTED_IDS = { STARTS.getOperatorString() };
+    
+    private Map<String, StartsEvaluator> cache        = Collections.emptyMap();
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  null );
+    }
+
+    /**
+     * @inheridDoc
+     */
+    public Evaluator getEvaluator(ValueType type,
+                                  Operator operator,
+                                  String parameterText) {
+        return this.getEvaluator( type,
+                                  operator.getOperatorString(),
+                                  operator.isNegated(),
+                                  parameterText );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public Evaluator getEvaluator(final ValueType type,
+                                  final String operatorId,
+                                  final boolean isNegated,
+                                  final String parameterText) {
+        if ( this.cache == Collections.EMPTY_MAP ) {
+            this.cache = new HashMap<String, StartsEvaluator>();
+        }
+        String key = isNegated + ":" + parameterText;
+        StartsEvaluator eval = this.cache.get( key );
+        if ( eval == null ) {
+            eval = new StartsEvaluator( type,
+                                       isNegated,
+                                       parameterText );
+            this.cache.put( key,
+                            eval );
+        }
+        return eval;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public String[] getEvaluatorIds() {
+        return SUPPORTED_IDS;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean isNegatable() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean operatesOnFactHandles() {
+        return true;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean supportsType(ValueType type) {
+        // supports all types, since it operates over fact handles
+        // Note: should we change this interface to allow checking of event classes only?
+        return true;
+    }
+
+    /**
+     * Implements the 'starts' evaluator itself
+     */
+    public static class StartsEvaluator extends BaseEvaluator {
+		private static final long serialVersionUID = 5622952247746290865L;
+		
+		private long                  startDev;
+        private long                  endMinDev, endMaxDev;
+
+        public StartsEvaluator(final ValueType type,
+                              final boolean isNegated,
+                              final String parameters) {
+            super( type,
+                   isNegated ? STARTS_NOT : STARTS );
+            this.parseParameters( parameters );
+        }
+        
+        @Override
+        public Object prepareObject(InternalFactHandle handle) {
+            return handle;
+        }
+        
+        public boolean evaluate(InternalWorkingMemory workingMemory,
+                                final Extractor extractor,
+                                final Object object1,
+                                final FieldValue object2) {
+            throw new RuntimeDroolsException( "The 'starts' operator can only be used to compare one event to another, and never to compare to literal constraints." );
+        }
+
+        public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                final VariableContextEntry context,
+                final Object left) {
+			
+        	if ( context.rightNull ) {
+        		return false;
+				}
+			long distStart = Math.abs(((EventFactHandle)((ObjectVariableContextEntry) context).right).getStartTimestamp() - ((EventFactHandle) left ).getStartTimestamp());
+			long distEnd = ((EventFactHandle) left ).getEndTimestamp() - ((EventFactHandle)((ObjectVariableContextEntry) context).right).getEndTimestamp();
+			return this.getOperator().isNegated() ^ ( distStart <= this.startDev 
+					&& distEnd >= this.endMinDev && distEnd <= this.endMaxDev );
+		}
+			
+		public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+			               final VariableContextEntry context,
+			               final Object right) {
+			if ( context.extractor.isNullValue( workingMemory,
+			                     right ) ) {
+			return false;
+			}
+			long distStart = Math.abs(((EventFactHandle) right ).getStartTimestamp() - ((EventFactHandle) ((ObjectVariableContextEntry) context).left).getStartTimestamp());
+			long distEnd = ((EventFactHandle) ((ObjectVariableContextEntry) context).left).getEndTimestamp() - ((EventFactHandle) right ).getEndTimestamp();
+			return this.getOperator().isNegated() ^ ( distStart <= this.startDev 
+					&& distEnd >= this.endMinDev && distEnd <= this.endMaxDev );
+		}
+			
+		public boolean evaluate(InternalWorkingMemory workingMemory,
+			     final Extractor extractor1,
+			     final Object object1,
+			     final Extractor extractor2,
+			     final Object object2) {
+			if ( extractor1.isNullValue( workingMemory,
+			              object1 ) ) {
+			return false;
+			}
+			long distStart = Math.abs(((EventFactHandle) object1 ).getStartTimestamp() - ((EventFactHandle) object2 ).getStartTimestamp());
+			long distEnd = ((EventFactHandle) object2 ).getEndTimestamp() - ((EventFactHandle) object1 ).getEndTimestamp();
+			return this.getOperator().isNegated() ^ ( distStart  <= this.startDev 
+					&& distEnd >= this.endMinDev && distEnd <= this.endMaxDev );
+		}
+
+        public String toString() {
+            return "starts[" + startDev + ", " + endMinDev + ", " + endMaxDev + "]";
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int PRIME = 31;
+            int result = super.hashCode();
+            result = PRIME * result + (int) (endMaxDev ^ (endMaxDev >>> 32));
+            result = PRIME * result + (int) (endMinDev ^ (endMinDev >>> 32));
+            result = PRIME * result + (int) (startDev ^ (startDev >>> 32));
+            return result;
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#equals(java.lang.Object)
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if ( this == obj ) return true;
+            if ( !super.equals( obj ) ) return false;
+            if ( getClass() != obj.getClass() ) return false;
+            final StartsEvaluator other = (StartsEvaluator) obj;
+            return endMaxDev == other.endMaxDev && endMinDev == other.endMinDev && startDev == other.startDev;
+        }
+
+        /**
+         * This methods tries to parse the string of parameters to customize 
+         * the evaluator.
+         * 
+         * @param parameters
+         */
+        private void parseParameters(String parameters) {
+            if ( parameters == null || parameters.trim().length() == 0 ) {
+                // exact matching at the beginning of the intervals, open bounded ranges for the ends
+                this.startDev = 0;
+                this.endMinDev = 1;
+                this.endMaxDev = Long.MAX_VALUE;
+                return;
+            }
+
+            try {
+                String[] ranges = parameters.split( "," );
+                if ( ranges.length == 1 ) {
+                    // exact matching at the beginning of the intervals
+                	// deterministic point in time for deviations of the ends of the intervals
+                	this.startDev = 0;
+                	this.endMinDev = Long.parseLong( ranges[0] );
+                    this.endMaxDev = this.endMinDev;
+                } else if ( ranges.length == 2 ) {
+                    // exact matching at the beginning of the intervals
+                	// range for deviations of the ends of the intervals 
+                	this.startDev = 0;
+                    this.endMinDev = Long.parseLong( ranges[0] );
+                    this.endMaxDev = Long.parseLong( ranges[1] );
+                } else if ( ranges.length == 3 ) {
+                	// max. deviation at the starts of the intervals
+                	// range for deviations of the ends of the intervals 
+                	this.startDev = Long.parseLong( ranges[0] );;
+                    this.endMinDev = Long.parseLong( ranges[1] );
+                    this.endMaxDev = Long.parseLong( ranges[2] );
+                } else {
+                    throw new RuntimeDroolsException( "[Starts Evaluator]: Not possible to parse parameters: '" + parameters + "'" );
+                }
+            } catch ( NumberFormatException e ) {
+                throw new RuntimeDroolsException( "[Starts Evaluator]: Not possible to parse parameters: '" + parameters + "'",
+                                                  e );
+            }
+        }
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/ArrayExtractor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/ArrayExtractor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/ArrayExtractor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,106 @@
+package org.drools.base.extractors;
+
+import java.lang.reflect.Method;
+
+import org.drools.base.ValueType;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.Extractor;
+import org.drools.util.ClassUtils;
+
+public class ArrayExtractor implements Extractor {
+    private final Extractor arrayExtractor;    
+    private final int index;
+    private final Class type;
+    
+    public ArrayExtractor(Extractor arrayExtractor, int index, Class type) {
+        this.arrayExtractor = arrayExtractor;
+        this.index = index;
+        this.type = type;
+    }
+    
+    public Class getExtractToClass() {
+        return type;        
+    }
+    
+    public String getExtractToClassName() {
+        return ClassUtils.canonicalName( type );        
+    }
+    
+    public boolean getBooleanValue(InternalWorkingMemory workingMemory, Object object) {
+        Object[] array = ( Object[] ) this.arrayExtractor.getValue( workingMemory, object );
+        return ( (Boolean)array[ this.index ]).booleanValue();
+    }
+    public byte getByteValue(InternalWorkingMemory workingMemory, Object object) {
+        Object[] array = ( Object[] ) this.arrayExtractor.getValue( workingMemory, object );
+        return ( (Number)array[ this.index ]).byteValue();
+    }
+    public char getCharValue(InternalWorkingMemory workingMemory, Object object) {
+        Object[] array = ( Object[] ) this.arrayExtractor.getValue( workingMemory, object );
+        return ( (Character)array[ this.index ]).charValue();
+    }
+    public double getDoubleValue(InternalWorkingMemory workingMemory, Object object) {
+        Object[] array = ( Object[] ) this.arrayExtractor.getValue( workingMemory, object );
+        return ( (Number)array[ this.index ]).doubleValue();
+    }
+
+    public float getFloatValue(InternalWorkingMemory workingMemory, Object object) {
+        Object[] array = ( Object[] ) this.arrayExtractor.getValue( workingMemory, object );
+        return ( (Number)array[ this.index ]).floatValue();
+    }
+
+    public int getIntValue(InternalWorkingMemory workingMemory, Object object) {
+        Object[] array = ( Object[] ) this.arrayExtractor.getValue( workingMemory, object );
+        return ( (Number)array[ this.index ]).intValue();
+    }
+    public long getLongValue(InternalWorkingMemory workingMemory, Object object) {
+        Object[] array = ( Object[] ) this.arrayExtractor.getValue( workingMemory, object );
+        return ( (Number) array[ this.index ]).longValue();
+    }
+    public Method getNativeReadMethod() {
+        throw new UnsupportedOperationException("cannot call a method on an array extractor" );
+    }
+    public short getShortValue(InternalWorkingMemory workingMemory, Object object) {
+        Object[] array = ( Object[] ) this.arrayExtractor.getValue( workingMemory, object );
+        return ( (Number)array[ this.index ]).shortValue();
+    }
+    public Object getValue(InternalWorkingMemory workingMemory, Object object) {
+        Object[] array = ( Object[] ) this.arrayExtractor.getValue( workingMemory, object );
+        return array[ this.index ];
+    }
+    public ValueType getValueType() {
+        return ValueType.OBJECT_TYPE;
+    }
+    public boolean isNullValue(InternalWorkingMemory workingMemory, Object object ) {
+        Object[] array = ( Object[] ) this.arrayExtractor.getValue( workingMemory, object );
+        return array[ this.index ] == null;
+    }
+    
+  public int getHashCode(InternalWorkingMemory workingMemory, Object object) {
+      Object[] array = ( Object[] ) this.arrayExtractor.getValue( workingMemory, object );
+      return array[ this.index ].hashCode();
+  }    
+
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + ((arrayExtractor == null) ? 0 : arrayExtractor.hashCode());
+        result = PRIME * result + index;
+        return result;
+    }
+
+    public boolean equals(Object obj) {
+        if ( this == obj ) return true;
+        if ( obj == null ) return false;
+        if ( getClass() != obj.getClass() ) return false;
+        final ArrayExtractor other = (ArrayExtractor) obj;
+        if ( arrayExtractor == null ) {
+            if ( other.arrayExtractor != null ) return false;
+        } else if ( !arrayExtractor.equals( other.arrayExtractor ) ) return false;
+        if ( index != other.index ) return false;
+        return true;
+    }
+
+    public boolean isGlobal() {
+        return false;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseBooleanClassFieldExtractor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseBooleanClassFieldExtractor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseBooleanClassFieldExtractor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.base.extractors;
+
+import java.lang.reflect.Method;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.BaseClassFieldExtractor;
+import org.drools.base.ValueType;
+import org.drools.common.InternalWorkingMemory;
+
+/**
+ * A Base class for primitive boolean class field
+ * extractors. This class centralizes type conversions.
+ *  
+ * @author etirelli
+ */
+public abstract class BaseBooleanClassFieldExtractor extends BaseClassFieldExtractor {
+
+    private static final long serialVersionUID = 400L;
+
+    public BaseBooleanClassFieldExtractor(final Class clazz,
+                                          final String fieldName) {
+        super( clazz,
+               fieldName );
+    }
+
+    /**
+     * This constructor is not supposed to be used from outside the class hirarchy
+     * 
+     * @param index
+     * @param fieldType
+     * @param valueType
+     */
+    protected BaseBooleanClassFieldExtractor(final int index,
+                                             final Class fieldType,
+                                             final ValueType valueType) {
+        super( index,
+               fieldType,
+               valueType );
+    }
+
+    public Object getValue(InternalWorkingMemory workingMemory, final Object object) {
+        return getBooleanValue( workingMemory, object ) ? Boolean.TRUE : Boolean.FALSE;
+    }
+
+    public abstract boolean getBooleanValue(InternalWorkingMemory workingMemory, Object object);
+
+    public byte getByteValue(InternalWorkingMemory workingMemory, final Object object) {
+        throw new RuntimeDroolsException( "Conversion to byte not supported from boolean" );
+    }
+
+    public char getCharValue(InternalWorkingMemory workingMemory, final Object object) {
+        throw new RuntimeDroolsException( "Conversion to char not supported from boolean" );
+    }
+
+    public double getDoubleValue(InternalWorkingMemory workingMemory, final Object object) {
+        throw new RuntimeDroolsException( "Conversion to double not supported from boolean" );
+    }
+
+    public float getFloatValue(InternalWorkingMemory workingMemory, final Object object) {
+        throw new RuntimeDroolsException( "Conversion to float not supported from boolean" );
+    }
+
+    public int getIntValue(InternalWorkingMemory workingMemory, final Object object) {
+        throw new RuntimeDroolsException( "Conversion to int not supported from boolean" );
+    }
+
+    public long getLongValue(InternalWorkingMemory workingMemory, final Object object) {
+        throw new RuntimeDroolsException( "Conversion to long not supported from boolean" );
+    }
+
+    public short getShortValue(InternalWorkingMemory workingMemory, final Object object) {
+        throw new RuntimeDroolsException( "Conversion to short not supported from boolean" );
+    }
+    
+    public boolean isNullValue(InternalWorkingMemory workingMemory, final Object object) {
+        return false;
+    }
+
+    public Method getNativeReadMethod() {
+        try {
+            return this.getClass().getDeclaredMethod( "getBooleanValue",
+                                                      new Class[]{InternalWorkingMemory.class, Object.class} );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( "This is a bug. Please report to development team: " + e.getMessage(),
+                                              e );
+        }
+    }
+
+    public int getHashCode(InternalWorkingMemory workingMemory, final Object object) {
+        return getBooleanValue( workingMemory, object ) ? 1231 : 1237;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseByteClassFieldExtractor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseByteClassFieldExtractor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseByteClassFieldExtractor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.base.extractors;
+
+import java.lang.reflect.Method;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.BaseClassFieldExtractor;
+import org.drools.base.ValueType;
+import org.drools.common.InternalWorkingMemory;
+
+/**
+ * A Base class for primitive byte class field
+ * extractors. This class centralizes type conversions.
+ *  
+ * @author etirelli
+ */
+public abstract class BaseByteClassFieldExtractor extends BaseClassFieldExtractor {
+
+    private static final long serialVersionUID = 400L;
+
+    public BaseByteClassFieldExtractor(final Class clazz,
+                                       final String fieldName) {
+        super( clazz,
+               fieldName );
+    }
+
+    /**
+     * This constructor is not supposed to be used from outside the class hirarchy
+     * 
+     * @param index
+     * @param fieldType
+     * @param valueType
+     */
+    protected BaseByteClassFieldExtractor(final int index,
+                                          final Class fieldType,
+                                          final ValueType valueType) {
+        super( index,
+               fieldType,
+               valueType );
+    }
+
+    public Object getValue(InternalWorkingMemory workingMemory, final Object object) {
+        return new Byte( getByteValue( workingMemory, object ) );
+    }
+
+    public boolean getBooleanValue(InternalWorkingMemory workingMemory, final Object object) {
+        throw new RuntimeDroolsException( "Conversion to boolean not supported from byte" );
+    }
+
+    public abstract byte getByteValue(InternalWorkingMemory workingMemory, Object object);
+
+    public char getCharValue(InternalWorkingMemory workingMemory, final Object object) {
+        throw new RuntimeDroolsException( "Conversion to char not supported from byte" );
+    }
+
+    public double getDoubleValue(InternalWorkingMemory workingMemory, final Object object) {
+        return getByteValue( workingMemory, object );
+    }
+
+    public float getFloatValue(InternalWorkingMemory workingMemory, final Object object) {
+        return getByteValue( workingMemory, object );
+    }
+
+    public int getIntValue(InternalWorkingMemory workingMemory, final Object object) {
+        return getByteValue( workingMemory, object );
+    }
+
+    public long getLongValue(InternalWorkingMemory workingMemory, final Object object) {
+        return getByteValue( workingMemory, object );
+    }
+
+    public short getShortValue(InternalWorkingMemory workingMemory, final Object object) {
+        return getByteValue( workingMemory, object );
+    }
+
+    public boolean isNullValue(InternalWorkingMemory workingMemory, final Object object) {
+        return false;
+    }
+    
+    public Method getNativeReadMethod() {
+        try {
+            return this.getClass().getDeclaredMethod( "getByteValue",
+                                                      new Class[]{InternalWorkingMemory.class, Object.class} );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( "This is a bug. Please report to development team: " + e.getMessage(),
+                                              e );
+        }
+    }
+
+    public int getHashCode(InternalWorkingMemory workingMemory, final Object object) {
+        return getByteValue( workingMemory, object );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseCharClassFieldExtractor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseCharClassFieldExtractor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseCharClassFieldExtractor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,86 @@
+package org.drools.base.extractors;
+
+import java.lang.reflect.Method;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.BaseClassFieldExtractor;
+import org.drools.base.ValueType;
+import org.drools.common.InternalWorkingMemory;
+
+public abstract class BaseCharClassFieldExtractor extends BaseClassFieldExtractor {
+
+    private static final long serialVersionUID = 400L;
+
+    public BaseCharClassFieldExtractor(final Class clazz,
+                                       final String fieldName) {
+        super( clazz,
+               fieldName );
+    }
+
+    /**
+     * This constructor is not supposed to be used from outside the class hirarchy
+     * 
+     * @param index
+     * @param fieldType
+     * @param valueType
+     */
+    protected BaseCharClassFieldExtractor(final int index,
+                                          final Class fieldType,
+                                          final ValueType valueType) {
+        super( index,
+               fieldType,
+               valueType );
+    }
+
+    public Object getValue(InternalWorkingMemory workingMemory, final Object object) {
+        return new Character( getCharValue( workingMemory, object ) );
+    }
+
+    public boolean getBooleanValue(InternalWorkingMemory workingMemory, final Object object) {
+        throw new RuntimeDroolsException( "Conversion to boolean not supported from char" );
+    }
+
+    public byte getByteValue(InternalWorkingMemory workingMemory, final Object object) {
+        return (byte) getCharValue( workingMemory, object );
+    }
+
+    public abstract char getCharValue(InternalWorkingMemory workingMemory, Object object);
+
+    public double getDoubleValue(InternalWorkingMemory workingMemory, final Object object) {
+        return getCharValue( workingMemory, object );
+    }
+
+    public float getFloatValue(InternalWorkingMemory workingMemory, final Object object) {
+        return getCharValue( workingMemory, object );
+    }
+
+    public int getIntValue(InternalWorkingMemory workingMemory, final Object object) {
+        return getCharValue( workingMemory, object );
+    }
+
+    public long getLongValue(InternalWorkingMemory workingMemory, final Object object) {
+        return getCharValue( workingMemory, object );
+    }
+
+    public short getShortValue(InternalWorkingMemory workingMemory, final Object object) {
+        return (short) getCharValue( workingMemory, object );
+    }
+
+    public boolean isNullValue(InternalWorkingMemory workingMemory, final Object object) {
+        return false;
+    }
+    
+    public Method getNativeReadMethod() {
+        try {
+            return this.getClass().getDeclaredMethod( "getCharValue",
+                                                      new Class[]{InternalWorkingMemory.class, Object.class} );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( "This is a bug. Please report to development team: " + e.getMessage(),
+                                              e );
+        }
+    }
+
+    public int getHashCode(InternalWorkingMemory workingMemory, final Object object) {
+        return getCharValue( workingMemory, object );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseDoubleClassFieldExtractor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseDoubleClassFieldExtractor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseDoubleClassFieldExtractor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,89 @@
+package org.drools.base.extractors;
+
+import java.lang.reflect.Method;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.BaseClassFieldExtractor;
+import org.drools.base.ValueType;
+import org.drools.common.InternalWorkingMemory;
+
+public abstract class BaseDoubleClassFieldExtractor extends BaseClassFieldExtractor {
+
+    private static final long serialVersionUID = 400L;
+
+    public BaseDoubleClassFieldExtractor(final Class clazz,
+                                         final String fieldName) {
+        super( clazz,
+               fieldName );
+    }
+
+    /**
+     * This constructor is not supposed to be used from outside the class hirarchy
+     * 
+     * @param index
+     * @param fieldType
+     * @param valueType
+     */
+    protected BaseDoubleClassFieldExtractor(final int index,
+                                            final Class fieldType,
+                                            final ValueType valueType) {
+        super( index,
+               fieldType,
+               valueType );
+    }
+
+    public Object getValue(InternalWorkingMemory workingMemory, final Object object) {
+        return new Double( getDoubleValue( workingMemory, object ) );
+    }
+
+    public boolean getBooleanValue(InternalWorkingMemory workingMemory, final Object object) {
+        throw new RuntimeDroolsException( "Conversion to boolean not supported from double" );
+    }
+
+    public byte getByteValue(InternalWorkingMemory workingMemory, final Object object) {
+        return (byte) getDoubleValue( workingMemory, object );
+
+    }
+
+    public char getCharValue(InternalWorkingMemory workingMemory, final Object object) {
+        throw new RuntimeDroolsException( "Conversion to char not supported from double" );
+    }
+
+    public abstract double getDoubleValue(InternalWorkingMemory workingMemory, Object object);
+
+    public float getFloatValue(InternalWorkingMemory workingMemory, final Object object) {
+        return (float) getDoubleValue( workingMemory, object );
+    }
+
+    public int getIntValue(InternalWorkingMemory workingMemory, final Object object) {
+        return (int) getDoubleValue( workingMemory, object );
+    }
+
+    public long getLongValue(InternalWorkingMemory workingMemory, final Object object) {
+        return (long) getDoubleValue( workingMemory, object );
+    }
+
+    public short getShortValue(InternalWorkingMemory workingMemory, final Object object) {
+        return (short) getDoubleValue( workingMemory, object );
+    }
+
+    public boolean isNullValue(InternalWorkingMemory workingMemory, final Object object) {
+        return false;
+    }
+
+    public Method getNativeReadMethod() {
+        try {
+            return this.getClass().getDeclaredMethod( "getDoubleValue",
+                                                      new Class[]{InternalWorkingMemory.class, Object.class} );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( "This is a bug. Please report to development team: " + e.getMessage(),
+                                              e );
+        }
+    }
+
+    public int getHashCode(InternalWorkingMemory workingMemory, final Object object) {
+        final long temp = Double.doubleToLongBits( getDoubleValue( workingMemory, object ) );
+        return (int) (temp ^ (temp >>> 32));
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseFloatClassFieldExtractor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseFloatClassFieldExtractor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseFloatClassFieldExtractor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,88 @@
+package org.drools.base.extractors;
+
+import java.lang.reflect.Method;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.BaseClassFieldExtractor;
+import org.drools.base.ValueType;
+import org.drools.common.InternalWorkingMemory;
+
+public abstract class BaseFloatClassFieldExtractor extends BaseClassFieldExtractor {
+
+    private static final long serialVersionUID = 400L;
+
+    public BaseFloatClassFieldExtractor(final Class clazz,
+                                        final String fieldName) {
+        super( clazz,
+               fieldName );
+    }
+
+    /**
+     * This constructor is not supposed to be used from outside the class hirarchy
+     * 
+     * @param index
+     * @param fieldType
+     * @param valueType
+     */
+    protected BaseFloatClassFieldExtractor(final int index,
+                                           final Class fieldType,
+                                           final ValueType valueType) {
+        super( index,
+               fieldType,
+               valueType );
+    }
+
+    public Object getValue(InternalWorkingMemory workingMemory, final Object object) {
+        return new Float( getFloatValue( workingMemory, object ) );
+    }
+
+    public boolean getBooleanValue(InternalWorkingMemory workingMemory, final Object object) {
+        throw new RuntimeDroolsException( "Conversion to boolean not supported from float" );
+    }
+
+    public byte getByteValue(InternalWorkingMemory workingMemory, final Object object) {
+        return (byte) getFloatValue( workingMemory, object );
+
+    }
+
+    public char getCharValue(InternalWorkingMemory workingMemory, final Object object) {
+        throw new RuntimeDroolsException( "Conversion to char not supported from float" );
+    }
+
+    public double getDoubleValue(InternalWorkingMemory workingMemory, final Object object) {
+        return getFloatValue( workingMemory, object );
+    }
+
+    public abstract float getFloatValue(InternalWorkingMemory workingMemory, Object object);
+
+    public int getIntValue(InternalWorkingMemory workingMemory, final Object object) {
+        return (int) getFloatValue( workingMemory, object );
+    }
+
+    public long getLongValue(InternalWorkingMemory workingMemory, final Object object) {
+        return (long) getFloatValue( workingMemory, object );
+    }
+
+    public short getShortValue(InternalWorkingMemory workingMemory, final Object object) {
+        return (short) getFloatValue( workingMemory, object );
+    }
+
+    public boolean isNullValue(InternalWorkingMemory workingMemory, final Object object) {
+        return false;
+    }
+
+    public Method getNativeReadMethod() {
+        try {
+            return this.getClass().getDeclaredMethod( "getFloatValue",
+                                                      new Class[]{InternalWorkingMemory.class, Object.class} );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( "This is a bug. Please report to development team: " + e.getMessage(),
+                                              e );
+        }
+    }
+
+    public int getHashCode(InternalWorkingMemory workingMemory, final Object object) {
+        return Float.floatToIntBits( getFloatValue( workingMemory, object ) );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseIntClassFieldExtractor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseIntClassFieldExtractor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseIntClassFieldExtractor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,87 @@
+package org.drools.base.extractors;
+
+import java.lang.reflect.Method;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.BaseClassFieldExtractor;
+import org.drools.base.ValueType;
+import org.drools.common.InternalWorkingMemory;
+
+public abstract class BaseIntClassFieldExtractor extends BaseClassFieldExtractor {
+
+    private static final long serialVersionUID = 400L;
+
+    public BaseIntClassFieldExtractor(final Class clazz,
+                                      final String fieldName) {
+        super( clazz,
+               fieldName );
+    }
+
+    /**
+     * This constructor is not supposed to be used from outside the class hirarchy
+     * 
+     * @param index
+     * @param fieldType
+     * @param valueType
+     */
+    protected BaseIntClassFieldExtractor(final int index,
+                                         final Class fieldType,
+                                         final ValueType valueType) {
+        super( index,
+               fieldType,
+               valueType );
+    }
+
+    public Object getValue(InternalWorkingMemory workingMemory, final Object object) {
+        return new Integer( getIntValue( workingMemory, object ) );
+    }
+
+    public boolean getBooleanValue(InternalWorkingMemory workingMemory, final Object object) {
+        throw new RuntimeDroolsException( "Conversion to boolean not supported from int" );
+    }
+
+    public byte getByteValue(InternalWorkingMemory workingMemory, final Object object) {
+        return (byte) getIntValue( workingMemory, object );
+
+    }
+
+    public char getCharValue(InternalWorkingMemory workingMemory, final Object object) {
+        throw new RuntimeDroolsException( "Conversion to char not supported from int" );
+    }
+
+    public double getDoubleValue(InternalWorkingMemory workingMemory, final Object object) {
+        return getIntValue( workingMemory, object );
+    }
+
+    public float getFloatValue(InternalWorkingMemory workingMemory, final Object object) {
+        return getIntValue( workingMemory, object );
+    }
+
+    public abstract int getIntValue(InternalWorkingMemory workingMemory, Object object);
+
+    public long getLongValue(InternalWorkingMemory workingMemory, final Object object) {
+        return getIntValue( workingMemory, object );
+    }
+
+    public short getShortValue(InternalWorkingMemory workingMemory, final Object object) {
+        return (short) getIntValue( workingMemory, object );
+    }
+
+    public boolean isNullValue(InternalWorkingMemory workingMemory, final Object object) {
+        return false;
+    }
+
+    public Method getNativeReadMethod() {
+        try {
+            return this.getClass().getDeclaredMethod( "getIntValue",
+                                                      new Class[]{InternalWorkingMemory.class, Object.class} );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( "This is a bug. Please report to development team: " + e.getMessage(),
+                                              e );
+        }
+    }
+
+    public int getHashCode(InternalWorkingMemory workingMemory, final Object object) {
+        return getIntValue( workingMemory, object );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseLongClassFieldExtractors.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseLongClassFieldExtractors.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseLongClassFieldExtractors.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,89 @@
+package org.drools.base.extractors;
+
+import java.lang.reflect.Method;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.BaseClassFieldExtractor;
+import org.drools.base.ValueType;
+import org.drools.common.InternalWorkingMemory;
+
+public abstract class BaseLongClassFieldExtractors extends BaseClassFieldExtractor {
+
+    private static final long serialVersionUID = 400L;
+
+    public BaseLongClassFieldExtractors(final Class clazz,
+                                        final String fieldName) {
+        super( clazz,
+               fieldName );
+    }
+
+    /**
+     * This constructor is not supposed to be used from outside the class hirarchy
+     * 
+     * @param index
+     * @param fieldType
+     * @param valueType
+     */
+    protected BaseLongClassFieldExtractors(final int index,
+                                           final Class fieldType,
+                                           final ValueType valueType) {
+        super( index,
+               fieldType,
+               valueType );
+    }
+
+    public Object getValue(InternalWorkingMemory workingMemory, final Object object) {
+        return new Long( getLongValue( workingMemory, object ) );
+    }
+
+    public boolean getBooleanValue(InternalWorkingMemory workingMemory, final Object object) {
+        throw new RuntimeDroolsException( "Conversion to boolean not supported from long" );
+    }
+
+    public byte getByteValue(InternalWorkingMemory workingMemory, final Object object) {
+        return (byte) getLongValue( workingMemory, object );
+
+    }
+
+    public char getCharValue(InternalWorkingMemory workingMemory, final Object object) {
+        throw new RuntimeDroolsException( "Conversion to char not supported from long" );
+    }
+
+    public double getDoubleValue(InternalWorkingMemory workingMemory, final Object object) {
+        return getLongValue( workingMemory, object );
+    }
+
+    public float getFloatValue(InternalWorkingMemory workingMemory, final Object object) {
+        return getLongValue( workingMemory, object );
+    }
+
+    public int getIntValue(InternalWorkingMemory workingMemory, final Object object) {
+        return (int) getLongValue( workingMemory, object );
+    }
+
+    public abstract long getLongValue(InternalWorkingMemory workingMemory, Object object);
+
+    public short getShortValue(InternalWorkingMemory workingMemory, final Object object) {
+        return (short) getLongValue( workingMemory, object );
+    }
+
+    public boolean isNullValue(InternalWorkingMemory workingMemory, final Object object) {
+        return false;
+    }
+
+    public Method getNativeReadMethod() {
+        try {
+            return this.getClass().getDeclaredMethod( "getLongValue",
+                                                      new Class[]{InternalWorkingMemory.class, Object.class} );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( "This is a bug. Please report to development team: " + e.getMessage(),
+                                              e );
+        }
+    }
+
+    public int getHashCode(InternalWorkingMemory workingMemory, final Object object) {
+        final long temp = getLongValue( workingMemory, object );
+        return (int) (temp ^ (temp >>> 32));
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseObjectClassFieldExtractor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseObjectClassFieldExtractor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseObjectClassFieldExtractor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,143 @@
+package org.drools.base.extractors;
+
+import java.lang.reflect.Method;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.BaseClassFieldExtractor;
+import org.drools.base.ValueType;
+import org.drools.common.InternalWorkingMemory;
+
+public abstract class BaseObjectClassFieldExtractor extends BaseClassFieldExtractor {
+
+    private static final long serialVersionUID = 400L;
+
+    protected BaseObjectClassFieldExtractor(final int index,
+                                            final Class fieldType,
+                                            final ValueType valueType) {
+        super( index,
+               fieldType,
+               valueType );
+    }
+
+    public BaseObjectClassFieldExtractor(final Class clazz,
+                                         final String fieldName) {
+        super( clazz,
+               fieldName );
+    }
+
+    public abstract Object getValue(InternalWorkingMemory workingMemory, Object object);
+
+    public boolean getBooleanValue(InternalWorkingMemory workingMemory, final Object object) {
+        // this can be improved by generating specific 
+        // bytecode generation in the subclass, avoiding the if instanceof
+        final Object value = getValue( workingMemory, object );
+        
+        if ( value instanceof Boolean ) {
+            return ((Boolean) value).booleanValue();
+        }
+        throw new RuntimeDroolsException( "Conversion to boolean not supported from " + value.getClass().getName() );
+    }
+
+    public byte getByteValue(InternalWorkingMemory workingMemory, final Object object) {
+        // this can be improved by generating specific 
+        // bytecode generation in the subclass, avoiding the if instanceof
+        final Object value = getValue( workingMemory, object );
+        
+        if ( value instanceof Number ) {
+            return ((Number) value).byteValue();
+        }
+        throw new RuntimeDroolsException( "Conversion to byte not supported from " + value.getClass().getName() );
+    }
+
+    public char getCharValue(InternalWorkingMemory workingMemory, final Object object) {
+        // this can be improved by generating specific 
+        // bytecode generation in the subclass, avoiding the if instanceof
+        final Object value = getValue( workingMemory, object );
+        
+        if ( value instanceof Character ) {
+            return ((Character) value).charValue();
+        } else if( value instanceof String && ((String)value).length() == 1 ) {
+            return ((String)value).charAt( 0 );
+        }
+        throw new RuntimeDroolsException( "Conversion to char not supported from " + value.getClass().getName() );
+    }
+
+    public double getDoubleValue(InternalWorkingMemory workingMemory, final Object object) {
+        // this can be improved by generating specific 
+        // bytecode generation in the subclass, avoiding the if instanceof
+        final Object value = getValue( workingMemory, object );
+        
+        if ( value instanceof Number ) {
+            return ((Number) value).doubleValue();
+        }
+        throw new RuntimeDroolsException( "Conversion to double not supported from " + value.getClass().getName() );
+    }
+
+    public float getFloatValue(InternalWorkingMemory workingMemory, final Object object) {
+        // this can be improved by generating specific 
+        // bytecode generation in the subclass, avoiding the if instanceof
+        final Object value = getValue( workingMemory, object );
+        
+        if ( value instanceof Number ) {
+            return ((Number) value).floatValue();
+        }
+        throw new RuntimeDroolsException( "Conversion to float not supported from " + value.getClass().getName() );
+    }
+
+    public int getIntValue(InternalWorkingMemory workingMemory, final Object object) {
+        // this can be improved by generating specific 
+        // bytecode generation in the subclass, avoiding the if instanceof
+        final Object value = getValue( workingMemory, object );
+        
+        if ( value instanceof Number ) {
+            return ((Number) value).intValue();
+        }
+        throw new RuntimeDroolsException( "Conversion to int not supported from " + value.getClass().getName() );
+    }
+
+    public long getLongValue(InternalWorkingMemory workingMemory, final Object object) {
+        // this can be improved by generating specific 
+        // bytecode generation in the subclass, avoiding the if instanceof
+        final Object value = getValue( workingMemory, object );
+        
+        if ( value instanceof Number ) {
+            return ((Number) value).longValue();
+        }
+        throw new RuntimeDroolsException( "Conversion to long not supported from " + value.getClass().getName() );
+    }
+
+    public short getShortValue(InternalWorkingMemory workingMemory, final Object object) {
+        // this can be improved by generating specific 
+        // bytecode generation in the subclass, avoiding the if instanceof
+        final Object value = getValue( workingMemory, object );
+
+        if ( value instanceof Number ) {
+            return ((Number) value).shortValue();
+        }
+        throw new RuntimeDroolsException( "Conversion to short not supported from " + value.getClass().getName() );
+    }
+    
+    public boolean isNullValue(InternalWorkingMemory workingMemory, final Object object) {
+        if (object == null) {
+            return true;
+        } else {
+            return getValue( workingMemory, object ) == null;
+        }
+    }
+
+    public Method getNativeReadMethod() {
+        try {
+            return this.getClass().getDeclaredMethod( "getValue",
+                                                      new Class[]{InternalWorkingMemory.class, Object.class} );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( "This is a bug. Please report to development team: " + e.getMessage(),
+                                              e );
+        }
+    }
+
+    public int getHashCode(InternalWorkingMemory workingMemory, final Object object) {
+        final Object value = getValue( workingMemory, object );
+        return (value != null) ? value.hashCode() : 0;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseShortClassFieldExtractor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseShortClassFieldExtractor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/BaseShortClassFieldExtractor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,87 @@
+package org.drools.base.extractors;
+
+import java.lang.reflect.Method;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.BaseClassFieldExtractor;
+import org.drools.base.ValueType;
+import org.drools.common.InternalWorkingMemory;
+
+public abstract class BaseShortClassFieldExtractor extends BaseClassFieldExtractor {
+
+    private static final long serialVersionUID = 400L;
+
+    public BaseShortClassFieldExtractor(final Class clazz,
+                                        final String fieldName) {
+        super( clazz,
+               fieldName );
+    }
+
+    /**
+     * This constructor is not supposed to be used from outside the class hirarchy
+     * 
+     * @param index
+     * @param fieldType
+     * @param valueType
+     */
+    protected BaseShortClassFieldExtractor(final int index,
+                                           final Class fieldType,
+                                           final ValueType valueType) {
+        super( index,
+               fieldType,
+               valueType );
+    }
+
+    public Object getValue(InternalWorkingMemory workingMemory, final Object object) {
+        return new Short( getShortValue( workingMemory, object ) );
+    }
+
+    public boolean getBooleanValue(InternalWorkingMemory workingMemory, final Object object) {
+        throw new RuntimeDroolsException( "Conversion to boolean not supported from short" );
+    }
+
+    public byte getByteValue(InternalWorkingMemory workingMemory, final Object object) {
+        return (byte) getShortValue( workingMemory, object );
+
+    }
+
+    public char getCharValue(InternalWorkingMemory workingMemory, final Object object) {
+        throw new RuntimeDroolsException( "Conversion to char not supported from short" );
+    }
+
+    public double getDoubleValue(InternalWorkingMemory workingMemory, final Object object) {
+        return getShortValue( workingMemory, object );
+    }
+
+    public float getFloatValue(InternalWorkingMemory workingMemory, final Object object) {
+        return getShortValue( workingMemory, object );
+    }
+
+    public int getIntValue(InternalWorkingMemory workingMemory, final Object object) {
+        return getShortValue( workingMemory, object );
+    }
+
+    public long getLongValue(InternalWorkingMemory workingMemory, final Object object) {
+        return getShortValue( workingMemory, object );
+    }
+
+    public abstract short getShortValue(InternalWorkingMemory workingMemory, Object object);
+    
+    public boolean isNullValue(InternalWorkingMemory workingMemory, final Object object) {
+        return false;
+    }
+
+    public Method getNativeReadMethod() {
+        try {
+            return this.getClass().getDeclaredMethod( "getShortValue",
+                                                      new Class[]{InternalWorkingMemory.class, Object.class} );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( "This is a bug. Please report to development team: " + e.getMessage(),
+                                              e );
+        }
+    }
+
+    public int getHashCode(InternalWorkingMemory workingMemory, final Object object) {
+        return getShortValue( workingMemory, object );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/MVELClassFieldExtractor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/MVELClassFieldExtractor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/MVELClassFieldExtractor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2006 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.
+ *
+ * Created on Jun 12, 2007
+ */
+package org.drools.base.extractors;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.ValueType;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldExtractor;
+import org.mvel.CompiledExpression;
+import org.mvel.ExpressionCompiler;
+import org.mvel.MVEL;
+
+/**
+ * A class field extractor that uses MVEL engine to extract the actual value for a given
+ * expression. We use MVEL to resolve nested accessor expressions.
+ * 
+ * @author etirelli
+ */
+public class MVELClassFieldExtractor extends BaseObjectClassFieldExtractor {
+    
+    private static final long serialVersionUID = 400L;
+
+    private CompiledExpression mvelExpression = null;
+    private Map extractors = null;
+    private Map variables = null; 
+
+    public MVELClassFieldExtractor(Class clazz,
+                                   String fieldName,
+                                   ClassLoader classLoader) {
+        super( -1, // index
+               Object.class, // fieldType
+               ValueType.determineValueType( Object.class ) ); // value type
+        this.extractors = new HashMap();
+        this.variables = new HashMap();
+
+        ExpressionCompiler compiler = new ExpressionCompiler( fieldName );
+        this.mvelExpression = compiler.compile();
+        
+        Set inputs = compiler.getParserContextState().getInputs().keySet();
+        for( Iterator it = inputs.iterator(); it.hasNext(); ) {
+            String basefield = (String) it.next();
+                        
+            Extractor extr = ClassFieldExtractorCache.getInstance().getExtractor(  clazz, basefield, classLoader );
+            this.extractors.put( basefield, extr );
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.base.extractors.BaseObjectClassFieldExtractor#getValue(java.lang.Object)
+     */
+    public Object getValue(InternalWorkingMemory workingMemory, Object object) {
+        for( Iterator it = this.extractors.entrySet().iterator(); it.hasNext(); ) {
+            Map.Entry entry = (Map.Entry) it.next();
+            String var = (String) entry.getKey();
+            FieldExtractor extr = (FieldExtractor) entry.getValue();
+            
+            this.variables.put( var, extr.getValue( workingMemory, object ));
+        }
+        return MVEL.executeExpression( mvelExpression, this.variables );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/SelfReferenceClassFieldExtractor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/SelfReferenceClassFieldExtractor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/extractors/SelfReferenceClassFieldExtractor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2006 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.base.extractors;
+
+import org.drools.base.ValueType;
+import org.drools.common.InternalWorkingMemory;
+
+/**
+ * A special field extractor for the self reference "this".
+ *  
+ * @author etirelli
+ */
+public class SelfReferenceClassFieldExtractor extends BaseObjectClassFieldExtractor {
+
+    private static final long serialVersionUID = 400L;
+
+    public SelfReferenceClassFieldExtractor(final Class clazz,
+                                            final String fieldName) {
+        super( -1, // index
+               clazz, // fieldType
+               ValueType.determineValueType( clazz ) ); // value type
+    }
+
+    public Object getValue(InternalWorkingMemory workingMemory, final Object object) {
+        //return (object instanceof ShadowProxy) ? ((ShadowProxy) object).getShadowedObject() : object;
+        return object;
+    }   
+    
+    public boolean isNullValue(InternalWorkingMemory workingMemory, final Object object) {
+        return getValue( workingMemory, object ) == null;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/field/BooleanFieldImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/field/BooleanFieldImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/field/BooleanFieldImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.base.field;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.spi.FieldValue;
+
+/**
+ * @author etirelli
+ *
+ */
+public class BooleanFieldImpl
+    implements
+    FieldValue {
+
+    private static final long serialVersionUID = 400L;
+    private final boolean     value;
+
+    public BooleanFieldImpl(final boolean value) {
+        this.value = value;
+    }
+
+    public Object getValue() {
+        return this.value ? Boolean.TRUE : Boolean.FALSE;
+    }
+
+    public String toString() {
+        return this.value ? Boolean.TRUE.toString() : Boolean.FALSE.toString();
+    }
+
+    public boolean getBooleanValue() {
+        return this.value;
+    }
+
+    public byte getByteValue() {
+        throw new RuntimeDroolsException( "Conversion to byte not supported for type boolean" );
+    }
+
+    public char getCharValue() {
+        throw new RuntimeDroolsException( "Conversion to char not supported for type boolean" );
+    }
+
+    public double getDoubleValue() {
+        throw new RuntimeDroolsException( "Conversion to double not supported for type boolean" );
+    }
+
+    public float getFloatValue() {
+        throw new RuntimeDroolsException( "Conversion to float not supported for type boolean" );
+    }
+
+    public int getIntValue() {
+        throw new RuntimeDroolsException( "Conversion to int not supported for type boolean" );
+    }
+
+    public long getLongValue() {
+        throw new RuntimeDroolsException( "Conversion to long not supported for type boolean" );
+    }
+
+    public short getShortValue() {
+        throw new RuntimeDroolsException( "Conversion to short not supported for type boolean" );
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+        if ( object == null || !(object instanceof BooleanFieldImpl) ) {
+            return false;
+        }
+        final BooleanFieldImpl other = (BooleanFieldImpl) object;
+
+        return this.value == other.value;
+    }
+
+    public int hashCode() {
+        return this.value ? 1 : 0;
+    }
+    
+    public boolean isNull() {
+        return false;
+    }
+
+    public boolean isBooleanField() {
+        return true;
+    }
+
+    public boolean isFloatNumberField() {
+        return false;
+    }
+
+    public boolean isIntegerNumberField() {
+        return false;
+    }
+
+    public boolean isObjectField() {
+        return false;
+    }
+
+    public boolean isCollectionField() {
+        return false;
+    }
+    
+    public boolean isStringField() {
+        return false;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/field/DoubleFieldImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/field/DoubleFieldImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/field/DoubleFieldImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,101 @@
+package org.drools.base.field;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.spi.FieldValue;
+
+public class DoubleFieldImpl
+    implements
+    FieldValue {
+
+    private static final long serialVersionUID = 400L;
+    private final double      value;
+
+    public DoubleFieldImpl(final double value) {
+        this.value = value;
+    }
+
+    public Object getValue() {
+        return new Double( this.value );
+    }
+
+    public String toString() {
+        return String.valueOf( this.value );
+    }
+
+    public boolean getBooleanValue() {
+        throw new RuntimeDroolsException( "Conversion to boolean not supported for type double" );
+    }
+
+    public byte getByteValue() {
+        return (byte) this.value;
+    }
+
+    public char getCharValue() {
+        return (char) this.value;
+    }
+
+    public double getDoubleValue() {
+        return this.value;
+    }
+
+    public float getFloatValue() {
+        return (float) this.value;
+    }
+
+    public int getIntValue() {
+        return (int) this.value;
+    }
+
+    public long getLongValue() {
+        return (long) this.value;
+    }
+
+    public short getShortValue() {
+        return (short) this.value;
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+        if ( object == null || !(object instanceof DoubleFieldImpl) ) {
+            return false;
+        }
+        final DoubleFieldImpl other = (DoubleFieldImpl) object;
+
+        return this.value == other.value;
+    }
+
+    public int hashCode() {
+        return (int) this.value;
+    }
+    
+    public boolean isNull() {
+        return false;
+    }
+
+    public boolean isBooleanField() {
+        return false;
+    }
+
+    public boolean isFloatNumberField() {
+        return true;
+    }
+
+    public boolean isIntegerNumberField() {
+        return false;
+    }
+
+    public boolean isObjectField() {
+        return false;
+    }
+    
+    public boolean isCollectionField() {
+        return false;
+    }
+
+    public boolean isStringField() {
+        return false;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/field/LongFieldImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/field/LongFieldImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/field/LongFieldImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,101 @@
+package org.drools.base.field;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.spi.FieldValue;
+
+public class LongFieldImpl
+    implements
+    FieldValue {
+
+    private static final long serialVersionUID = 400L;
+    private final long        value;
+
+    public LongFieldImpl(final long value) {
+        this.value = value;
+    }
+
+    public Object getValue() {
+        return new Long( this.value );
+    }
+
+    public String toString() {
+        return String.valueOf( this.value );
+    }
+
+    public boolean getBooleanValue() {
+        throw new RuntimeDroolsException( "Conversion to boolean not supported for type long" );
+    }
+
+    public byte getByteValue() {
+        return (byte) this.value;
+    }
+
+    public char getCharValue() {
+        return (char) this.value;
+    }
+
+    public double getDoubleValue() {
+        return this.value;
+    }
+
+    public float getFloatValue() {
+        return this.value;
+    }
+
+    public int getIntValue() {
+        return (int) this.value;
+    }
+
+    public long getLongValue() {
+        return this.value;
+    }
+
+    public short getShortValue() {
+        return (short) this.value;
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+        if ( object == null || !(object instanceof LongFieldImpl) ) {
+            return false;
+        }
+        final LongFieldImpl other = (LongFieldImpl) object;
+
+        return this.value == other.value;
+    }
+
+    public int hashCode() {
+        return (int) this.value;
+    }
+    
+    public boolean isNull() {
+        return false;
+    }
+
+    public boolean isBooleanField() {
+        return false;
+    }
+
+    public boolean isFloatNumberField() {
+        return false;
+    }
+
+    public boolean isIntegerNumberField() {
+        return true;
+    }
+
+    public boolean isObjectField() {
+        return false;
+    }
+
+    public boolean isCollectionField() {
+        return false;
+    }
+
+    public boolean isStringField() {
+        return false;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/field/ObjectFieldImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/field/ObjectFieldImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/field/ObjectFieldImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,173 @@
+package org.drools.base.field;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Collection;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.spi.FieldValue;
+
+public class ObjectFieldImpl
+    implements
+    FieldValue {
+
+    private static final long serialVersionUID = 400L;
+    private final Object      value;
+    
+    private final boolean     isCollection;
+    private final boolean     isNumber;
+    private final boolean     isBoolean;
+    private final boolean     isCharacter;
+    private final boolean     isString;
+
+    public ObjectFieldImpl(final Object value) {
+        this.value = value;
+        this.isCollection = value instanceof Collection;
+        this.isNumber = value instanceof Number;
+        this.isBoolean = value instanceof Boolean;
+        this.isCharacter = value instanceof Character;
+        this.isString = value instanceof String;
+    }
+
+    public Object getValue() {
+        return this.value;
+    }
+
+    public String toString() {
+        return this.value == null ? "null" : this.value.toString();
+    }
+
+    public boolean getBooleanValue() {
+        if ( isBoolean ) {
+            return ((Boolean) this.value).booleanValue();
+        } else if( isString ) {
+            return Boolean.valueOf( (String) this.value ).booleanValue();
+        }
+        throw new RuntimeDroolsException( "Conversion to boolean not supported for type: " + this.value.getClass() );
+    }
+
+    public byte getByteValue() {
+        if ( isNumber ) {
+            return ((Number) this.value).byteValue();
+        } else if( isString ) {
+            return Byte.valueOf( (String) this.value ).byteValue();
+        } 
+        throw new RuntimeDroolsException( "Conversion to byte not supported for type: " + this.value.getClass() );
+    }
+
+    public char getCharValue() {
+        if ( isCharacter ) {
+            return ((Character) this.value).charValue();
+        } else if( isString && ((String) this.value).length() == 1 ) {
+            return ( (String) this.value ).charAt( 0 );
+        }
+        throw new RuntimeDroolsException( "Conversion to char not supported for type: " + this.value.getClass() );
+    }
+
+    public double getDoubleValue() {
+        if ( isNumber ) {
+            return ((Number) this.value).doubleValue();
+        } else if( isString ) {
+            return Double.valueOf( (String) this.value ).doubleValue();
+        }
+        throw new RuntimeDroolsException( "Conversion to double not supported for type: " + this.value.getClass() );
+    }
+
+    public float getFloatValue() {
+        if ( isNumber ) {
+            return ((Number) this.value).floatValue();
+        } else if( isString ) {
+            return Float.valueOf( (String) this.value ).floatValue();
+        }
+        throw new RuntimeDroolsException( "Conversion to float not supported for type: " + this.value.getClass() );
+    }
+
+    public int getIntValue() {
+        if ( isNumber ) {
+            return ((Number) this.value).intValue();
+        } else if( isString ) {
+            return Integer.valueOf( (String) this.value ).intValue();
+        }
+        throw new RuntimeDroolsException( "Conversion to int not supported for type: " + this.value.getClass() );
+    }
+
+    public long getLongValue() {
+        if ( isNumber ) {
+            return ((Number) this.value).longValue();
+        } else if( isString ) {
+            return Long.valueOf( (String) this.value ).longValue();
+        }
+        throw new RuntimeDroolsException( "Conversion to long not supported for type: " + this.value.getClass() );
+    }
+
+    public short getShortValue() {
+        if ( isNumber ) {
+            return ((Number) this.value).shortValue();
+        } else if( isString ) {
+            return Short.valueOf( (String) this.value ).shortValue();
+        }
+        throw new RuntimeDroolsException( "Conversion to short not supported for type: " + this.value.getClass() );
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+        if ( object == null || !(object instanceof ObjectFieldImpl) ) {
+            return false;
+        }
+        final ObjectFieldImpl other = (ObjectFieldImpl) object;
+
+        return (((this.value == null) && (other.value == null)) || ((this.value != null) && (this.value.equals( other.value ))));
+    }
+
+    public int hashCode() {
+        if ( this.value != null ) {
+            return this.value.hashCode();
+        } else {
+            return 0;
+        }
+    }
+    
+    public boolean isNull() {
+        return value == null;
+    }
+
+    public boolean isBooleanField() {
+        return false;
+    }
+
+    public boolean isFloatNumberField() {
+        return false;
+    }
+
+    public boolean isIntegerNumberField() {
+        return false;
+    }
+
+    public boolean isObjectField() {
+        return true;
+    }
+    
+    public boolean isCollectionField() {
+        return this.isCollection;
+    }
+    
+    public boolean isStringField() {
+        return this.isString;
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/DroolsMVELFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/DroolsMVELFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/DroolsMVELFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,281 @@
+package org.drools.base.mvel;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.WorkingMemory;
+import org.drools.common.DroolsObjectInputStream;
+import org.drools.reteoo.ReteTuple;
+import org.drools.rule.Declaration;
+import org.drools.rule.Package;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.Tuple;
+import org.mvel.CompileException;
+import org.mvel.DataConversion;
+import org.mvel.integration.VariableResolver;
+import org.mvel.integration.impl.BaseVariableResolverFactory;
+import org.mvel.integration.impl.LocalVariableResolverFactory;
+import org.mvel.integration.impl.StaticMethodImportResolverFactory;
+
+public class DroolsMVELFactory extends BaseVariableResolverFactory
+    implements
+    LocalVariableResolverFactory,
+    Serializable,
+    Cloneable {
+
+    private static final long serialVersionUID = 400L;
+
+    /**
+     * Holds the instance of the variables.
+     */
+    private Object[]          tupleObjects;
+
+    private KnowledgeHelper   knowledgeHelper;
+
+    private Object            object;
+
+    private Map               localDeclarations;
+
+    private Map               previousDeclarations;
+
+    private Map               globals;
+
+    private WorkingMemory     workingMemory;
+
+    private Map               localVariables;
+
+    static {
+        //for handling dates as string literals
+        DataConversion.addConversionHandler( Date.class, new MVELDateCoercion() );
+        DataConversion.addConversionHandler( Calendar.class, new MVELCalendarCoercion() );
+    }
+
+    public DroolsMVELFactory(final Map previousDeclarations,
+                             final Map localDeclarations,
+                             final Map globals) {
+        this( previousDeclarations,
+              localDeclarations,
+              globals,
+              null );
+    }
+
+    public DroolsMVELFactory(final Map previousDeclarations,
+                             final Map localDeclarations,
+                             final Map globals,
+                             final List[] externals) {
+        this.previousDeclarations = previousDeclarations;
+        this.localDeclarations = localDeclarations;
+        this.globals = globals;
+
+        if ( externals != null && MVELDebugHandler.isDebugMode() ) {
+            for ( int i = 0; i < externals.length; i++ ) {
+                for ( Iterator it = externals[i].iterator(); it.hasNext(); ) {
+                    String identifier = (String) it.next();
+                    isResolveable( identifier );
+                }
+            }
+        }
+    }
+
+//    public void writeExternal(final ObjectOutput stream) throws IOException {
+//        setNextFactory( null );
+//        stream.writeObject( this.previousDeclarations );
+//        stream.writeObject( this.localDeclarations );
+//        stream.writeObject( this.globals );
+//        stream.writeObject( this.variableResolvers );
+//    }
+//
+//    public void readExternal(final ObjectInput stream) throws IOException,
+//                                                      ClassNotFoundException {
+//        DroolsObjectInputStream droolsInputStream = (DroolsObjectInputStream) stream;
+//
+//        this.previousDeclarations = (Map) droolsInputStream.readObject();
+//        this.localDeclarations = (Map) droolsInputStream.readObject();
+//        this.globals = (Map) droolsInputStream.readObject();
+//        this.variableResolvers = (Map) droolsInputStream.readObject();
+//
+//        StaticMethodImportResolverFactory factory = new StaticMethodImportResolverFactory();
+//        setNextFactory( factory );
+//
+//        Package pkg = droolsInputStream.getPackage();
+//        ClassLoader classLoader = pkg.getPackageCompilationData().getClassLoader();
+//        for ( Iterator it = pkg.getStaticImports().iterator(); it.hasNext(); ) {
+//            String staticImportEntry = (String) it.next();
+//            addStaticImport( factory,
+//                             staticImportEntry,
+//                             classLoader );
+//        }
+//    }
+
+    public static void addStaticImport(StaticMethodImportResolverFactory factory,
+                                       String staticImportEntry,
+                                       ClassLoader classLoader) {
+        int index = staticImportEntry.lastIndexOf( '.' );
+        String className = staticImportEntry.substring( 0,
+                                                        index );
+        String methodName = staticImportEntry.substring( index + 1 );
+
+        try {
+            Class cls = classLoader.loadClass( className );
+            Method[] methods = cls.getDeclaredMethods();
+            for ( int i = 0; i < methods.length; i++ ) {
+                if ( methods[i].getName().equals( methodName ) ) {
+                    factory.createVariable( methodName,
+                                            methods[i] );
+                    break;
+                }
+            }
+        } catch ( ClassNotFoundException e ) {
+            throw new RuntimeException( "Unable to dynamically load method '" + staticImportEntry + "'" );
+        }
+
+    }
+
+    public Map getVariableResolvers() {
+        return this.variableResolvers;
+    }
+
+    public Object getObject() {
+        return this.object;
+    }
+
+    public WorkingMemory getWorkingMemory() {
+        return this.workingMemory;
+    }
+
+    public void setContext(final Tuple tuple,
+                           final KnowledgeHelper knowledgeHelper,
+                           final Object object,
+                           final WorkingMemory workingMemory,
+                           final Map variables) {
+        if ( tuple != null ) {
+            this.tupleObjects = ((ReteTuple) tuple).toObjectArray();
+        }
+        this.knowledgeHelper = knowledgeHelper;
+        this.object = object;
+        this.workingMemory = workingMemory;
+        if ( variables == null ) {
+            if ( this.localVariables == null ) {
+                this.localVariables = new HashMap();
+            } else {
+                this.localVariables.clear();
+            }            
+        } else {
+            this.localVariables = variables;
+        }
+    }
+
+    public KnowledgeHelper getKnowledgeHelper() {
+        return this.knowledgeHelper;
+    }
+
+    public Object getValue(final Declaration declaration) {
+        int i = declaration.getPattern().getOffset();
+        return this.tupleObjects[i];
+    }
+
+    public Object getValue(final String identifier) {
+        return this.workingMemory.getGlobal( identifier );
+    }
+
+    public Object getLocalValue(final String identifier) {
+        return this.localVariables.get( identifier );
+    }
+
+    public void setLocalValue(final String identifier,
+                              final Object value) {
+        this.localVariables.put( identifier,
+                                 value );
+    }
+
+    public VariableResolver createVariable(String name,
+                                           Object value) {
+        VariableResolver vr = getVariableResolver( name );
+        if ( vr == null ) {
+            addResolver( name,
+                         vr = new LocalVariableResolver( this,
+                                                         name ) );
+        }
+        
+        vr.setValue( value );
+        return vr;        
+    }
+
+    public VariableResolver createVariable(String name,
+                                           Object value,
+                                           Class type) {
+        VariableResolver vr = getVariableResolver( name );
+        if ( vr == null ) {
+            addResolver( name,
+                         vr = new LocalVariableResolver( this,
+                                                         name,
+                                                         type ) );
+        }        
+        
+        vr.setValue( value );
+        return vr;
+    }
+
+    public boolean isResolveable(String name) {
+        if ( DroolsMVELKnowledgeHelper.DROOLS.equals( name ) ) {
+            addResolver( DroolsMVELKnowledgeHelper.DROOLS,
+                         new DroolsMVELKnowledgeHelper( this ) );
+            return true;
+
+        } else if ( this.variableResolvers != null && this.variableResolvers.containsKey( name ) ) {
+            return true;
+        } else if ( this.previousDeclarations != null && this.previousDeclarations.containsKey( name ) ) {
+            addResolver( name,
+                         new DroolsMVELPreviousDeclarationVariable( (Declaration) this.previousDeclarations.get( name ),
+                                                                    this ) );
+            return true;
+        } else if ( this.localDeclarations != null && this.localDeclarations.containsKey( name ) ) {
+            addResolver( name,
+                         new DroolsMVELLocalDeclarationVariable( (Declaration) this.localDeclarations.get( name ),
+                                                                 this ) );
+            return true;
+        } else if ( this.globals.containsKey( name ) ) {
+            addResolver( name,
+                         new DroolsMVELGlobalVariable( name,
+                                                       (Class) this.globals.get( name ),
+                                                       this ) );
+            return true;
+        }  else if ( nextFactory != null ) {
+            return nextFactory.isResolveable( name );
+        }
+
+        return false;
+    }
+
+    private void addResolver(String name,
+                             VariableResolver vr) {
+        if ( this.variableResolvers == null ) {
+            this.variableResolvers = new HashMap();
+        }
+        this.variableResolvers.put( name,
+                                    vr );
+    }
+
+    public boolean isTarget(String name) {
+        if ( this.variableResolvers != null ) {
+            return this.variableResolvers.containsKey( name );
+        } else {
+            return false;
+        }
+    }
+
+    public Object clone() {
+        return new DroolsMVELFactory( this.previousDeclarations,
+                                      this.localDeclarations,
+                                      this.globals );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/DroolsMVELGlobalVariable.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/DroolsMVELGlobalVariable.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/DroolsMVELGlobalVariable.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,57 @@
+package org.drools.base.mvel;
+
+import java.io.Serializable;
+
+import org.mvel.integration.VariableResolver;
+
+public class DroolsMVELGlobalVariable
+    implements
+    VariableResolver,
+    Serializable {
+
+    private String            name;
+    private Class             knownType;
+    private DroolsMVELFactory factory;
+
+    public DroolsMVELGlobalVariable(final String identifier,
+                                    final Class knownType,
+                                    final DroolsMVELFactory factory) {
+        this.name = identifier;
+        this.factory = factory;
+        this.knownType = knownType;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public Class getKnownType() {
+        return this.knownType;
+    }
+
+    public Object getValue() {
+        return this.factory.getValue( this.name );
+    }
+
+    public void setValue(final Object value) {
+        throw new UnsupportedOperationException( "External Variable identifer='" + getName() + "' type='" + getKnownType() + "' is final, it cannot be set" );
+    }
+
+    public int getFlags() {
+        return 0;
+    }
+
+    /**
+     * Not used in drools.
+     */
+    public Class getType() {
+        return this.knownType;
+    }
+
+    /**
+     * Not used in drools.
+     */
+    public void setStaticType(Class arg0) {
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/DroolsMVELKnowledgeHelper.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/DroolsMVELKnowledgeHelper.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/DroolsMVELKnowledgeHelper.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,54 @@
+package org.drools.base.mvel;
+
+import java.io.Serializable;
+
+import org.drools.rule.Declaration;
+import org.drools.spi.KnowledgeHelper;
+import org.mvel.integration.VariableResolver;
+
+public class DroolsMVELKnowledgeHelper
+    implements
+    VariableResolver,
+    Serializable  {
+
+    private DroolsMVELFactory factory;
+    public static final String DROOLS = "drools";
+
+    public DroolsMVELKnowledgeHelper(final DroolsMVELFactory factory) {
+        this.factory = factory;
+    }
+
+    public String getName() {
+        return DROOLS;
+    }
+
+    public Class getKnownType() {
+        return KnowledgeHelper.class;
+    }
+
+    public Object getValue() {
+        return this.factory.getKnowledgeHelper();
+    }    
+
+    public void setValue(final Object value) {
+        throw new UnsupportedOperationException( "External Variable identifer='" + getName() + "' type='" + getKnownType() + "' is final, it cannot be set" );
+    }
+
+    public int getFlags() {
+        return 0;
+    }
+
+    /**
+     * Not used in drools.
+     */
+    public Class getType() {
+        return KnowledgeHelper.class;
+    }
+
+    /**
+     * Not used in drools.
+     */
+    public void setStaticType(Class arg0) {
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/DroolsMVELLocalDeclarationVariable.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/DroolsMVELLocalDeclarationVariable.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/DroolsMVELLocalDeclarationVariable.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,53 @@
+package org.drools.base.mvel;
+
+import java.io.Serializable;
+
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.Declaration;
+import org.mvel.integration.VariableResolver;
+
+public class DroolsMVELLocalDeclarationVariable
+    implements
+    VariableResolver,
+    Serializable  {
+
+    private Declaration       declaration;
+    private DroolsMVELFactory factory;
+
+    public DroolsMVELLocalDeclarationVariable(final Declaration declaration,
+                                              final DroolsMVELFactory factory) {
+        this.declaration = declaration;
+        this.factory = factory;
+    }
+
+    public String getName() {
+        return this.declaration.getIdentifier();
+    }
+
+    public Class getKnownType() {
+        return this.declaration.getExtractor().getExtractToClass();
+    }
+
+    public Object getValue() {
+        return this.declaration.getValue( (InternalWorkingMemory) this.factory.getWorkingMemory(), this.factory.getObject() );
+    }
+
+    public void setValue(final Object value) {
+        throw new UnsupportedOperationException( "External Variable identifer='" + getName() + "' type='" + getKnownType() + "' is final, it cannot be set" );
+    }
+
+    public int getFlags() {
+        return 0;
+    }
+
+    public Class getType() {
+        return this.declaration.getExtractor().getExtractToClass();
+    }
+    
+    /**
+     * Not used in drools.
+     */
+    public void setStaticType(Class arg0) {
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/DroolsMVELPreviousDeclarationVariable.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/DroolsMVELPreviousDeclarationVariable.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/DroolsMVELPreviousDeclarationVariable.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,56 @@
+package org.drools.base.mvel;
+
+import java.io.Serializable;
+
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.Declaration;
+import org.mvel.integration.VariableResolver;
+
+public class DroolsMVELPreviousDeclarationVariable
+    implements
+    VariableResolver,
+    Serializable  {
+
+    private Declaration       declaration;
+    private DroolsMVELFactory factory;
+
+    public DroolsMVELPreviousDeclarationVariable(final Declaration declaration,
+                                                 final DroolsMVELFactory factory) {
+        this.declaration = declaration;
+        this.factory = factory;
+    }
+
+    public String getName() {
+        return this.declaration.getIdentifier();
+    }
+
+    public Class getKnownType() {
+        return this.declaration.getExtractor().getExtractToClass();
+    }
+
+    public Object getValue() {
+        return this.declaration.getValue( (InternalWorkingMemory) this.factory.getWorkingMemory(), this.factory.getValue( this.declaration ) );
+    }    
+
+    public void setValue(final Object value) {
+        throw new UnsupportedOperationException( "External Variable identifer='" + getName() + "' type='" + getKnownType() + "' is final, it cannot be set" );
+    }
+
+    public int getFlags() {
+        return 0;
+    }
+
+    /**
+     * Not used in drools.
+     */
+    public Class getType() {
+        return this.declaration.getExtractor().getExtractToClass();
+    }
+
+    /**
+     * Not used in drools.
+     */
+    public void setStaticType(Class arg0) {
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/LocalVariableResolver.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/LocalVariableResolver.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/LocalVariableResolver.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,109 @@
+/**
+ * MVEL (The MVFLEX Expression Language)
+ *
+ * Copyright (C) 2007 Christopher Brock, MVFLEX/Valhalla Project and the Codehaus
+ *
+ * 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.base.mvel;
+
+import org.mvel.CompileException;
+import org.mvel.DataConversion;
+import org.mvel.integration.VariableResolver;
+
+import java.util.Map;
+
+public class LocalVariableResolver implements VariableResolver {
+    private String name;
+    private Class knownType;
+    private DroolsMVELFactory factory;
+
+    private boolean cache = false;
+
+    public LocalVariableResolver(DroolsMVELFactory factory, String name) {
+        this.factory = factory;
+        this.name = name;
+    }
+
+    public LocalVariableResolver(DroolsMVELFactory factory, String name, Class knownType) {
+        this.name = name;
+        this.knownType = knownType;
+        this.factory = factory;
+    }
+
+    public LocalVariableResolver(DroolsMVELFactory factory, String name, boolean cache) {
+        this.factory = factory;
+        this.name = name;
+        this.cache = cache;
+    }
+
+    public LocalVariableResolver(DroolsMVELFactory factory, String name, Class knownType, boolean cache) {
+        this.name = name;
+        this.knownType = knownType;
+        this.factory = factory;
+        this.cache = cache;
+    }
+
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public void setStaticType(Class knownType) {
+        this.knownType = knownType;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public Class getType() {
+        return knownType;
+    }
+
+    public void setValue(Object value) {
+        if (knownType != null && value != null && value.getClass() != knownType) {
+            if (!DataConversion.canConvert(knownType, value.getClass())) {
+                throw new CompileException("cannot assign " + value.getClass().getName() + " to type: "
+                        + knownType.getName());
+            }
+            try {
+                value = DataConversion.convert(value, knownType);
+            }
+            catch (Exception e) {
+                throw new CompileException("cannot convert value of " + value.getClass().getName()
+                        + " to: " + knownType.getName());
+            }
+        }
+        
+        this.factory.setLocalValue( this.name, value );
+    }
+
+    public Object getValue() {
+        return this.factory.getLocalValue( this.name );
+    }
+
+    public int getFlags() {
+        return 0;
+    }
+
+
+    public boolean isCache() {
+        return cache;
+    }
+
+    public void setCache(boolean cache) {
+        this.cache = cache;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELAccumulator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELAccumulator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELAccumulator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Jun 20, 2007
+ */
+package org.drools.base.mvel;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.WorkingMemory;
+import org.drools.common.InternalFactHandle;
+import org.drools.rule.Declaration;
+import org.drools.spi.Accumulator;
+import org.drools.spi.Tuple;
+import org.mvel.MVEL;
+
+/**
+ * An MVEL accumulator implementation
+ * 
+ * @author etirelli
+ */
+public class MVELAccumulator
+    implements
+    Accumulator {
+
+    private static final long       serialVersionUID = 400L;
+
+    private final DroolsMVELFactory model;
+    private final Serializable      init;
+    private final Serializable      action;
+    private final Serializable      reverse;
+    private final Serializable      result;
+
+    public MVELAccumulator(final DroolsMVELFactory factory,
+                           final Serializable init,
+                           final Serializable action,
+                           final Serializable reverse,
+                           final Serializable result) {
+        super();
+        this.model = factory;
+        this.init = init;
+        this.action = action;
+        this.reverse = reverse;
+        this.result = result;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.spi.Accumulator#createContext()
+     */
+    public Object createContext() {
+        return new HashMap();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.spi.Accumulator#init(java.lang.Object, org.drools.spi.Tuple, org.drools.rule.Declaration[], org.drools.WorkingMemory)
+     */
+    public void init(Object workingMemoryContext,
+                     Object context,
+                     Tuple leftTuple,
+                     Declaration[] declarations,
+                     WorkingMemory workingMemory) throws Exception {
+        DroolsMVELFactory factory = (DroolsMVELFactory) workingMemoryContext;
+        factory.setContext( leftTuple,
+                            null,
+                            null,
+                            workingMemory,
+                            (Map) context );
+        MVEL.executeExpression( this.init,
+                                null,
+                                factory );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.spi.Accumulator#accumulate(java.lang.Object, org.drools.spi.Tuple, org.drools.common.InternalFactHandle, org.drools.rule.Declaration[], org.drools.rule.Declaration[], org.drools.WorkingMemory)
+     */
+    public void accumulate(Object workingMemoryContext,
+                           Object context,
+                           Tuple leftTuple,
+                           InternalFactHandle handle,
+                           Declaration[] declarations,
+                           Declaration[] innerDeclarations,
+                           WorkingMemory workingMemory) throws Exception {
+        DroolsMVELFactory factory = (DroolsMVELFactory) workingMemoryContext;
+        factory.setContext( leftTuple,
+                            null,
+                            handle.getObject(),
+                            workingMemory,
+                            (Map) context );
+        MVEL.executeExpression( this.action,
+                                null,
+                                factory );
+    }
+
+    public void reverse(Object workingMemoryContext,
+                        Object context,
+                        Tuple leftTuple,
+                        InternalFactHandle handle,
+                        Declaration[] declarations,
+                        Declaration[] innerDeclarations,
+                        WorkingMemory workingMemory) throws Exception {
+        DroolsMVELFactory factory = (DroolsMVELFactory) workingMemoryContext;
+        factory.setContext( leftTuple,
+                            null,
+                            handle.getObject(),
+                            workingMemory,
+                            (Map) context );
+        MVEL.executeExpression( this.reverse,
+                                null,
+                                factory );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.spi.Accumulator#getResult(java.lang.Object, org.drools.spi.Tuple, org.drools.rule.Declaration[], org.drools.WorkingMemory)
+     */
+    public Object getResult(Object workingMemoryContext,
+                            Object context,
+                            Tuple leftTuple,
+                            Declaration[] declarations,
+                            WorkingMemory workingMemory) throws Exception {
+        DroolsMVELFactory factory = (DroolsMVELFactory) workingMemoryContext;
+        factory.setContext( leftTuple,
+                            null,
+                            null,
+                            workingMemory,
+                            (Map) context );
+        final Object result = MVEL.executeExpression( this.result,
+                                                      null,
+                                                      factory );
+        return result;
+    }
+
+    public boolean supportsReverse() {
+        return this.reverse != null;
+    }
+
+    public Object createWorkingMemoryContext() {
+        return this.model.clone();
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELAction.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELAction.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELAction.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,62 @@
+package org.drools.base.mvel;
+
+import java.io.Serializable;
+
+import org.drools.WorkingMemory;
+import org.drools.spi.Action;
+import org.drools.spi.Consequence;
+import org.drools.spi.KnowledgeHelper;
+import org.mvel.CompiledExpression;
+import org.mvel.MVEL;
+import org.mvel.debug.DebugTools;
+
+public class MVELAction
+    implements
+    Action,
+    Serializable {
+    private static final long       serialVersionUID = 400L;
+
+    private final Serializable      expr;
+    private final DroolsMVELFactory factory;
+
+    public MVELAction(final Serializable expr,
+                      final DroolsMVELFactory factory) {
+        this.expr = expr;
+        this.factory = factory;
+    }
+    
+    public String getDialect() {
+        return "mvel";
+    }
+
+    public void execute(final WorkingMemory workingMemory) throws Exception {
+        this.factory.setContext( null,
+                                 null,
+                                 null,
+                                 workingMemory,
+                                 null );
+        CompiledExpression compexpr = (CompiledExpression) this.expr;
+
+        //Receive breakpoints from debugger
+        MVELDebugHandler.prepare();
+
+        if ( MVELDebugHandler.isDebugMode() ) {
+            if ( MVELDebugHandler.verbose ) {
+                System.out.println( DebugTools.decompile( compexpr ) );
+            }
+            MVEL.executeDebugger( compexpr,
+                                  null,
+                                  this.factory );
+        } else {
+            MVEL.executeExpression( compexpr,
+                                    null,
+                                    this.factory );
+        }
+
+    }
+
+    public Serializable getCompExpr() {
+        return expr;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELCalendarCoercion.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELCalendarCoercion.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELCalendarCoercion.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,28 @@
+package org.drools.base.mvel;
+
+import java.util.Calendar;
+
+import org.drools.util.DateUtils;
+import org.mvel.ConversionHandler;
+
+public class MVELCalendarCoercion implements ConversionHandler {
+
+    public boolean canConvertFrom(Class cls) {
+        if (cls == String.class || cls.isAssignableFrom( Calendar.class )) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public Object convertFrom(Object o) {
+        if (o instanceof String) {
+            Calendar cal = Calendar.getInstance();
+            cal.setTime( DateUtils.parseDate( (String) o) );
+            return cal;
+        } else {
+            return o;
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELConsequence.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELConsequence.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELConsequence.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,58 @@
+package org.drools.base.mvel;
+
+import java.io.Serializable;
+
+import org.drools.WorkingMemory;
+import org.drools.spi.Consequence;
+import org.drools.spi.KnowledgeHelper;
+import org.mvel.CompiledExpression;
+import org.mvel.MVEL;
+import org.mvel.debug.DebugTools;
+
+public class MVELConsequence
+    implements
+    Consequence,
+    Serializable {
+    private static final long       serialVersionUID = 400L;
+
+    private final Serializable      expr;
+    private final DroolsMVELFactory factory;
+
+    public MVELConsequence(final Serializable expr,
+                           final DroolsMVELFactory factory) {
+        this.expr = expr;
+        this.factory = factory;
+    }
+
+    public void evaluate(final KnowledgeHelper knowledgeHelper,
+                         final WorkingMemory workingMemory) throws Exception {
+        this.factory.setContext( knowledgeHelper.getTuple(),
+                                 knowledgeHelper,
+                                 null,
+                                 workingMemory,
+                                 null );
+        CompiledExpression compexpr = (CompiledExpression) this.expr;
+
+        //Receive breakpoints from debugger
+        MVELDebugHandler.prepare();
+
+        if ( MVELDebugHandler.isDebugMode() ) {
+            if ( MVELDebugHandler.verbose ) {
+                System.out.println( DebugTools.decompile( compexpr ) );
+            }
+            MVEL.executeDebugger( compexpr,
+                                  null,
+                                  this.factory );
+        } else {
+            MVEL.executeExpression( compexpr,
+                                    null,
+                                    this.factory );
+        }
+
+    }
+
+    public Serializable getCompExpr() {
+        return expr;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELDateCoercion.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELDateCoercion.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELDateCoercion.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,26 @@
+package org.drools.base.mvel;
+
+import java.util.Date;
+
+import org.drools.util.DateUtils;
+import org.mvel.ConversionHandler;
+
+public class MVELDateCoercion implements ConversionHandler {
+
+    public boolean canConvertFrom(Class cls) {
+        if (cls == String.class || cls.isAssignableFrom( Date.class )) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public Object convertFrom(Object o) {
+        if (o instanceof String) {
+            return DateUtils.parseDate( (String) o);
+        } else {
+            return o;
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELDebugHandler.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELDebugHandler.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELDebugHandler.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,129 @@
+package org.drools.base.mvel;
+
+import org.mvel.MVELRuntime;
+import org.mvel.debug.Debugger;
+import org.mvel.debug.Frame;
+
+/**
+ * Debug Handler for MVEL dialect.
+ *
+ * Takes care of registering breakpoints and calling required methods
+ * to trigger eclipse debugger to keep breakpoints in sync etc.
+ *
+ * @author Ahti Kitsik
+ *
+ */
+public final class MVELDebugHandler {
+
+    private static int onBreakReturn = Debugger.CONTINUE;
+
+    public final static String DEBUG_LAUNCH_KEY="mvel.debugger";
+
+    private static Boolean debugMode = null;
+
+    public static final boolean verbose = false;
+
+	static {
+		MVELRuntime.setThreadDebugger(new MVELDebugger());
+	}
+
+	/**
+	 * Notify remote debugger that runtime is ready to get latest breakpoint
+	 * information
+	 *
+	 */
+	public static void receiveBreakpoints() {
+	}
+
+	/**
+	 * This is catched by the remote debugger
+	 *
+	 * @param frame
+	 */
+	private final static int onBreak(Frame frame) {
+        // We always fall back to Debugger.CONTINUE after each onBreak to avoid eternal step-over flag
+        //int oldReturn = onBreakReturn;
+        //onBreakReturn = Debugger.CONTINUE;
+        //return oldReturn;
+		if (verbose) {
+            System.out.println("Continuing with "+(onBreakReturn==Debugger.CONTINUE?"continue":"step-over"));
+        }
+        return onBreakReturn;
+	}
+
+    protected final static void registerBreakpoint(String sourceName, int lineNumber) {
+        if (verbose) {
+            System.out.println("Registering breakpoint for "+sourceName+":"+lineNumber);
+        }
+        MVELRuntime.registerBreakpoint( sourceName, lineNumber );
+    }
+
+    protected final static void clearAllBreakpoints() {
+        if (verbose) {
+            System.out.println("Clearing all breakpoints");
+        }
+        MVELRuntime.clearAllBreakpoints();
+    }
+
+    protected final static void removeBreakpoint(String sourceName, int lineNumber) {
+        if (verbose) {
+            System.out.println("Removing breakpoint from "+sourceName+":"+lineNumber);
+        }
+        MVELRuntime.removeBreakpoint( sourceName, lineNumber );
+    }
+
+	private static class MVELDebugger implements Debugger {
+
+        public MVELDebugger() {
+        }
+
+		public int onBreak(Frame frame) {
+			if (verbose) {
+			    System.out.println("onBreak call for "+frame.getSourceName()+":"+frame.getLineNumber());
+            }
+			return MVELDebugHandler.onBreak(frame);
+			// This call is supposed to be catched by the remote debugger
+		}
+
+	}
+
+    protected final static void setOnBreakReturn(int value) {
+        onBreakReturn = value;
+    }
+
+    /**
+     * Do nothing for now. ensures that class is loaded prior debug handler
+     */
+    public static void prepare() {
+    	//do nothing
+    }
+
+    /**
+     * Returns current debug mode.<br/>
+     * Holds lazy initialized internal reference to improve performance.<br/>
+     * Therefore you can't change System property "mvel.debugger" after isDebugMode is called at least once.<br/>
+     * <br/>
+     * To update debug mode at runtime use {@link MVELDebugHandler#setDebugMode(boolean)}<br/>
+     * @return <code>true</code> if debug mode is enabled.
+     */
+    public static boolean isDebugMode() {
+        if (debugMode==null) {
+            debugMode = Boolean.valueOf(System.getProperty(DEBUG_LAUNCH_KEY));
+        }
+        return debugMode.booleanValue();
+    }
+
+    /**
+     * Sets debug mode on/off.<br/>
+     * Updates local MVELDebugHandler property and System property "mvel.debugger"<br/>
+     * <br/>
+     * There's no need to ever call this method unless you write junit tests!<br/>
+     *
+     * @param b is Debug enabled?
+     */
+    public static void setDebugMode(boolean b) {
+        debugMode = Boolean.valueOf( b );
+        System.setProperty( DEBUG_LAUNCH_KEY, debugMode.toString());
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELEvalExpression.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELEvalExpression.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELEvalExpression.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,42 @@
+package org.drools.base.mvel;
+
+import java.io.Serializable;
+
+import org.drools.WorkingMemory;
+import org.drools.rule.Declaration;
+import org.drools.spi.EvalExpression;
+import org.drools.spi.Tuple;
+import org.mvel.MVEL;
+
+public class MVELEvalExpression
+    implements
+    EvalExpression,
+    Serializable  {
+      
+
+    private static final long       serialVersionUID = 400L;
+
+    private final Serializable      expr;
+    private final DroolsMVELFactory factory;
+
+    public MVELEvalExpression(final Serializable expr,
+                              final DroolsMVELFactory factory) {
+        this.expr = expr;
+        this.factory = factory;
+    }
+
+    public boolean evaluate(final Tuple tuple,
+                            final Declaration[] requiredDeclarations,
+                            final WorkingMemory workingMemory) throws Exception {
+        this.factory.setContext( tuple,
+                                 null,
+                                 null,
+                                 workingMemory,
+                                 null );
+        final Boolean result = (Boolean) MVEL.executeExpression( this.expr,
+                                                                 new Object(),
+                                                                 this.factory );
+        return result.booleanValue();
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELPredicateExpression.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELPredicateExpression.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELPredicateExpression.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,42 @@
+package org.drools.base.mvel;
+
+import java.io.Serializable;
+
+import org.drools.WorkingMemory;
+import org.drools.rule.Declaration;
+import org.drools.spi.PredicateExpression;
+import org.drools.spi.Tuple;
+import org.mvel.MVEL;
+
+public class MVELPredicateExpression
+    implements
+    PredicateExpression,
+    Serializable  {
+    private static final long       serialVersionUID = 400L;
+
+    private final Serializable      expr;
+    private final DroolsMVELFactory factory;
+
+    public MVELPredicateExpression(final Serializable expr,
+                                   final DroolsMVELFactory factory) {
+        this.expr = expr;
+        this.factory = factory;
+    }
+
+    public boolean evaluate(final Object object,
+                            final Tuple tuple,
+                            final Declaration[] previousDeclarations,
+                            final Declaration[] requiredDeclarations,
+                            final WorkingMemory workingMemory) throws Exception {
+        this.factory.setContext( tuple,
+                                 null,
+                                 object,
+                                 workingMemory,
+                                 null );
+        final Boolean result = (Boolean) MVEL.executeExpression( this.expr,
+                                                                 object,
+                                                                 this.factory );
+        return result.booleanValue();
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELReturnValueEvaluator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELReturnValueEvaluator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELReturnValueEvaluator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,69 @@
+package org.drools.base.mvel;
+
+import java.io.Serializable;
+
+import org.drools.WorkingMemory;
+import org.drools.spi.Action;
+import org.drools.spi.Consequence;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.ReturnValueEvaluator;
+import org.mvel.CompiledExpression;
+import org.mvel.MVEL;
+import org.mvel.debug.DebugTools;
+
+public class MVELReturnValueEvaluator
+    implements
+    ReturnValueEvaluator,
+    Serializable {
+    private static final long       serialVersionUID = 400L;
+
+    private final Serializable      expr;
+    private final DroolsMVELFactory factory;
+
+    public MVELReturnValueEvaluator(final Serializable expr,
+                      final DroolsMVELFactory factory) {
+        this.expr = expr;
+        this.factory = factory;
+    }
+    
+    public String getDialect() {
+        return "mvel";
+    }
+
+    public Object evaluate(final WorkingMemory workingMemory) throws Exception {
+        this.factory.setContext( null,
+                                 null,
+                                 null,
+                                 workingMemory,
+                                 null );
+        CompiledExpression compexpr = (CompiledExpression) this.expr;
+
+        //Receive breakpoints from debugger
+        MVELDebugHandler.prepare();
+
+        Object value;
+        if ( MVELDebugHandler.isDebugMode() ) {
+            if ( MVELDebugHandler.verbose ) {
+                System.out.println( DebugTools.decompile( compexpr ) );
+            }
+            value = MVEL.executeDebugger( compexpr,
+                                  null,
+                                  this.factory );
+        } else {
+            value = MVEL.executeExpression( compexpr,
+                                    null,
+                                    this.factory );
+        }
+        
+        if ( !(value instanceof Boolean) ) {
+            throw new RuntimeException("Constraints must return boolean values" );
+        }
+        return ((Boolean)value).booleanValue();        
+
+    }
+
+    public Serializable getCompExpr() {
+        return expr;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELReturnValueExpression.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELReturnValueExpression.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELReturnValueExpression.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,43 @@
+package org.drools.base.mvel;
+
+import java.io.Serializable;
+
+import org.drools.WorkingMemory;
+import org.drools.rule.Declaration;
+import org.drools.spi.FieldValue;
+import org.drools.spi.ReturnValueExpression;
+import org.drools.spi.Tuple;
+import org.mvel.MVEL;
+
+public class MVELReturnValueExpression
+    implements
+    ReturnValueExpression,
+    Serializable  {
+    private static final long       serialVersionUID = 400L;
+
+    private final Serializable      expr;
+    private final DroolsMVELFactory factory;
+
+    public MVELReturnValueExpression(final Serializable expr,
+                                     final DroolsMVELFactory factory) {
+        this.expr = expr;
+        this.factory = factory;
+    }
+
+    public FieldValue evaluate(final Object object,
+                               final Tuple tuple,
+                               final Declaration[] previousDeclarations,
+                               final Declaration[] requiredDeclarations,
+                               final WorkingMemory workingMemory) throws Exception {
+        this.factory.setContext( tuple,
+                                 null,
+                                 object,
+                                 workingMemory,
+                                 null );
+
+        return org.drools.base.FieldFactory.getFieldValue( MVEL.executeExpression( this.expr,
+                                                                                   null,
+                                                                                   this.factory ) );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELSalienceExpression.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELSalienceExpression.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/base/mvel/MVELSalienceExpression.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,37 @@
+package org.drools.base.mvel;
+
+import java.io.Serializable;
+
+import org.drools.WorkingMemory;
+import org.drools.spi.Salience;
+import org.drools.spi.Tuple;
+import org.mvel.MVEL;
+
+public class MVELSalienceExpression
+    implements
+    Salience,
+    Serializable {
+
+    private static final long       serialVersionUID = 400L;
+
+    private final Serializable      expr;
+    private final DroolsMVELFactory factory;
+
+    public MVELSalienceExpression(final Serializable expr,
+                                  final DroolsMVELFactory factory) {
+        this.expr = expr;
+        this.factory = factory;
+    }
+
+    public int getValue(final Tuple tuple,
+                        final WorkingMemory workingMemory) {
+        this.factory.setContext( tuple,
+                                 null,
+                                 null,
+                                 workingMemory,
+                                 null );
+        return ((Number) MVEL.executeExpression( this.expr,
+                                                  this.factory )).intValue();
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/AbstractFactHandleFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/AbstractFactHandleFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/AbstractFactHandleFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,141 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.WorkingMemory;
+import org.drools.spi.FactHandleFactory;
+import org.drools.util.PrimitiveLongStack;
+
+public abstract class AbstractFactHandleFactory
+    implements
+    FactHandleFactory {
+
+    /**
+     * 
+     */
+    private static final long          serialVersionUID = 400L;
+
+    protected final PrimitiveLongStack factHandlePool   = new PrimitiveLongStack();
+
+    /** The fact id. */
+    private long                       id;
+
+    /** The number of facts created - used for recency. */
+    private long                       counter;
+
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.FactHandleFactory#newFactHandle()
+     */
+    public final InternalFactHandle newFactHandle( final Object object, final boolean isEvent, final WorkingMemory workingMemory ) {
+        if ( !this.factHandlePool.isEmpty() ) {
+            return newFactHandle( this.factHandlePool.pop(),
+                                  object, 
+                                  isEvent,
+                                  workingMemory );
+        }
+
+        return newFactHandle( this.id++,
+                              object,
+                              isEvent,
+                              workingMemory );
+    }
+    
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.FactHandleFactory#newFactHandle()
+     */
+    public final InternalFactHandle newFactHandle( final Object object, final boolean isEvent, long currentClockTime, final WorkingMemory workingMemory ) {
+        if ( !this.factHandlePool.isEmpty() ) {
+            return newFactHandle( this.factHandlePool.pop(),
+                                  object, 
+                                  isEvent,
+                                  currentClockTime,
+                                  workingMemory );
+        }
+
+        return newFactHandle( this.id++,
+                              object,
+                              isEvent,
+                              currentClockTime,
+                              workingMemory );
+    }
+    
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.FactHandleFactory#newFactHandle(long)
+     */
+    protected final InternalFactHandle newFactHandle(final long id,
+                                                     final Object object,
+                                                     final boolean isEvent, 
+                                                     final WorkingMemory workingMemory ) {
+        return newFactHandle( id,
+                              object,
+                              this.counter++,
+                              isEvent,
+                              workingMemory );
+    }
+    
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.FactHandleFactory#newFactHandle(long)
+     */
+    protected final InternalFactHandle newFactHandle(final long id,
+                                                     final Object object,
+                                                     final boolean isEvent,
+                                                     final long clockTime,
+                                                     final WorkingMemory workingMemory ) {
+        return newFactHandle( id,
+                              object,
+                              this.counter++,
+                              isEvent,
+                              clockTime,
+                              workingMemory );
+    }
+    
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.FactHandleFactory#newFactHandle(long)
+     */
+    protected abstract InternalFactHandle newFactHandle(final long id,
+                                                        final Object object,
+                                                        final long recency,
+                                                        final boolean isEvent, 
+                                                        final WorkingMemory workingMemory );
+    
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.FactHandleFactory#newFactHandle(long)
+     */
+    protected abstract InternalFactHandle newFactHandle(final long id,
+                                                        final Object object,
+                                                        final long recency,
+                                                        final boolean isEvent,
+                                                        final long clockTime,
+                                                        final WorkingMemory workingMemory );
+    
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.FactHandleFactory#increaseFactHandleRecency(org.drools.FactHandle)
+     */
+    public final void increaseFactHandleRecency(final InternalFactHandle factHandle) {
+        factHandle.setRecency( this.counter++ );
+    }
+
+    public void destroyFactHandle(final InternalFactHandle factHandle) {
+        this.factHandlePool.push( factHandle.getId() );
+        factHandle.invalidate();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.FactHandleFactory#newInstance()
+     */
+    public abstract FactHandleFactory newInstance();
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/AbstractRuleBase.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/AbstractRuleBase.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/AbstractRuleBase.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,859 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.drools.FactException;
+import org.drools.PackageIntegrationException;
+import org.drools.RuleBase;
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuleIntegrationException;
+import org.drools.StatefulSession;
+import org.drools.concurrent.CommandExecutor;
+import org.drools.concurrent.ExecutorService;
+import org.drools.event.RuleBaseEventListener;
+import org.drools.event.RuleBaseEventSupport;
+import org.drools.objenesis.Objenesis;
+import org.drools.objenesis.ObjenesisStd;
+import org.drools.process.core.Process;
+import org.drools.rule.CompositePackageClassLoader;
+import org.drools.rule.ImportDeclaration;
+import org.drools.rule.InvalidPatternException;
+import org.drools.rule.MapBackedClassLoader;
+import org.drools.rule.Package;
+import org.drools.rule.PackageCompilationData;
+import org.drools.rule.Rule;
+import org.drools.rule.TypeDeclaration;
+import org.drools.spi.ExecutorServiceFactory;
+import org.drools.spi.FactHandleFactory;
+import org.drools.util.ObjectHashSet;
+
+/**
+ * Implementation of <code>RuleBase</code>.
+ *
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter</a>
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ *
+ * @version $Id: RuleBaseImpl.java,v 1.5 2005/08/14 22:44:12 mproctor Exp $
+ */
+abstract public class AbstractRuleBase
+    implements
+    InternalRuleBase,
+    Externalizable {
+    // ------------------------------------------------------------
+    // Instance members
+    // ------------------------------------------------------------
+    protected String                                   id;
+
+    protected int                                      workingMemoryCounter;
+
+    protected RuleBaseConfiguration                    config;
+
+    protected Map<String, Package>                     pkgs;
+
+    protected Map                                      processes;
+
+    protected Map                                      agendaGroupRuleTotals;
+
+    protected transient CompositePackageClassLoader    packageClassLoader;
+
+    protected transient MapBackedClassLoader           classLoader;
+
+    private transient Objenesis                        objenesis;
+
+    /** The fact handle factory. */
+    protected FactHandleFactory                        factHandleFactory;
+
+    protected Map                                      globals;
+
+    private ReloadPackageCompilationData               reloadPackageCompilationData = null;
+
+    private RuleBaseEventSupport                       eventSupport                 = new RuleBaseEventSupport( this );
+
+    /**
+     * WeakHashMap to keep references of WorkingMemories but allow them to be
+     * garbage collected
+     */
+    protected transient ObjectHashSet                  statefulSessions;
+
+    // wms used for lock list during dynamic updates
+    InternalWorkingMemory[]                            wms;
+
+    // indexed used to track invariant lock
+    int                                                lastAquiredLock;
+
+    // lock for entire rulebase, used for dynamic updates
+    protected final ReentrantLock                      lock                         = new ReentrantLock();
+
+    private int                                        additionsSinceLock;
+    private int                                        removalsSinceLock;
+
+    private transient Map<Class< ? >, TypeDeclaration> classTypeDeclaration;
+
+    /**
+     * Default constructor - for Externalizable. This should never be used by a user, as it
+     * will result in an invalid state for the instance.
+     */
+    public AbstractRuleBase() {
+
+    }
+
+    public synchronized int nextWorkingMemoryCounter() {
+        return this.workingMemoryCounter++;
+    }
+
+    /**
+     * Construct.
+     *
+     * @param rete
+     *            The rete network.
+     */
+    public AbstractRuleBase(final String id,
+                            final RuleBaseConfiguration config,
+                            final FactHandleFactory factHandleFactory) {
+        if ( id != null ) {
+            this.id = id;
+        } else {
+            this.id = "default";
+        }
+        this.config = (config != null) ? config : new RuleBaseConfiguration();
+        this.config.makeImmutable();
+        this.factHandleFactory = factHandleFactory;
+
+        if ( this.config.isSequential() ) {
+            this.agendaGroupRuleTotals = new HashMap();
+        }
+
+        this.packageClassLoader = new CompositePackageClassLoader( this.config.getClassLoader() );
+        this.classLoader = new MapBackedClassLoader( this.config.getClassLoader() );
+        this.packageClassLoader.addClassLoader( this.classLoader );
+        this.pkgs = new HashMap<String, Package>();
+        this.processes = new HashMap();
+        this.globals = new HashMap();
+        this.statefulSessions = new ObjectHashSet();
+        this.objenesis = createObjenesis();
+
+        this.classTypeDeclaration = new HashMap<Class< ? >, TypeDeclaration>();
+    }
+
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+
+    /**
+     * Handles the write serialization of the Package. Patterns in Rules may reference generated data which cannot be serialized by default methods.
+     * The Package uses PackageCompilationData to hold a reference to the generated bytecode. The generated bytecode must be restored before any Rules.
+     *
+     */
+    public void doWriteExternal(final ObjectOutput stream) throws IOException {
+        stream.writeObject( this.pkgs );
+
+        // Rules must be restored by an ObjectInputStream that can resolve using a given ClassLoader to handle seaprately by storing as
+        // a byte[]
+        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        final ObjectOutput out = new ObjectOutputStream( bos );
+        out.writeObject( this.id );
+        out.writeObject( this.processes );
+        out.writeObject( this.agendaGroupRuleTotals );
+        out.writeObject( this.factHandleFactory );
+        out.writeObject( this.globals );
+        out.writeObject( this.config );
+
+        this.eventSupport.removeEventListener( RuleBaseEventListener.class );
+        out.writeObject( this.eventSupport );
+
+        stream.writeObject( bos.toByteArray() );
+    }
+
+    /**
+     * Handles the read serialization of the Package. Patterns in Rules may reference generated data which cannot be serialized by default methods.
+     * The Package uses PackageCompilationData to hold a reference to the generated bytecode; which must be restored before any Rules.
+     * A custom ObjectInputStream, able to resolve classes against the bytecode in the PackageCompilationData, is used to restore the Rules.
+     *
+     */
+    public void doReadExternal(final ObjectInput stream) throws IOException,
+                                                        ClassNotFoundException {
+        // PackageCompilationData must be restored before Rules as it has the ClassLoader needed to resolve the generated code references in Rules
+        this.pkgs = (Map) stream.readObject();
+
+        if ( stream instanceof DroolsObjectInputStream ) {
+            final DroolsObjectInputStream parentStream = (DroolsObjectInputStream) stream;
+            parentStream.setRuleBase( this );
+            this.packageClassLoader = new CompositePackageClassLoader( parentStream.getClassLoader() );
+            this.classLoader = new MapBackedClassLoader( parentStream.getClassLoader() );
+        } else {
+            this.packageClassLoader = new CompositePackageClassLoader( Thread.currentThread().getContextClassLoader() );
+            this.classLoader = new MapBackedClassLoader( Thread.currentThread().getContextClassLoader() );
+        }
+
+        this.packageClassLoader.addClassLoader( this.classLoader );
+        this.objenesis = createObjenesis();
+
+        for ( final Iterator it = this.pkgs.values().iterator(); it.hasNext(); ) {
+            this.packageClassLoader.addClassLoader( ((Package) it.next()).getPackageCompilationData().getClassLoader() );
+        }
+
+        // Return the rules stored as a byte[]
+        final byte[] bytes = (byte[]) stream.readObject();
+
+        //  Use a custom ObjectInputStream that can resolve against a given classLoader
+        final DroolsObjectInputStream childStream = new DroolsObjectInputStream( new ByteArrayInputStream( bytes ),
+                                                                                 this.packageClassLoader );
+        childStream.setRuleBase( this );
+
+        this.id = (String) childStream.readObject();
+        this.processes = (Map) childStream.readObject();
+        this.agendaGroupRuleTotals = (Map) childStream.readObject();
+        this.factHandleFactory = (FactHandleFactory) childStream.readObject();
+        this.globals = (Map) childStream.readObject();
+
+        this.config = (RuleBaseConfiguration) childStream.readObject();
+        this.config.setClassLoader( childStream.getClassLoader() );
+
+        this.eventSupport = (RuleBaseEventSupport) childStream.readObject();
+        this.eventSupport.setRuleBase( this );
+
+        this.statefulSessions = new ObjectHashSet();
+        
+        this.populateTypeDeclarationMaps();
+    }
+
+    private void populateTypeDeclarationMaps() {
+        this.classTypeDeclaration = new HashMap<Class<?>, TypeDeclaration>();
+        for( Package pkg : this.pkgs.values() ) {
+            for( TypeDeclaration type : pkg.getTypeDeclarations().values() ) {
+                this.classTypeDeclaration.put( type.getTypeClass(), type );
+            }
+        }
+    }
+
+    /**
+     * Creates Objenesis instance for the RuleBase. 
+     * @return a standart Objenesis instanse with caching turned on.
+     */
+    protected Objenesis createObjenesis() {
+        return new ObjenesisStd( true );
+    }
+
+    /**
+     * @return the id
+     */
+    public String getId() {
+        return this.id;
+    }
+
+    /**
+     * @see RuleBase
+     */
+    public StatefulSession newStatefulSession() {
+        return newStatefulSession( true );
+    }
+
+    /**
+     * @see RuleBase
+     */
+    abstract public StatefulSession newStatefulSession(boolean keepReference);
+
+    public synchronized void disposeStatefulSession(final StatefulSession statefulSession) {
+        this.statefulSessions.remove( statefulSession );
+        for ( Iterator it = statefulSession.getRuleBaseUpdateListeners().iterator(); it.hasNext(); ) {
+            this.removeEventListener( (RuleBaseEventListener) it.next() );
+        }
+    }
+
+    /**
+     * @see RuleBase
+     */
+    public FactHandleFactory getFactHandleFactory() {
+        return this.factHandleFactory;
+    }
+
+    public FactHandleFactory newFactHandleFactory() {
+        return this.factHandleFactory.newInstance();
+    }
+
+    public Process[] getProcesses() {
+        return (Process[]) this.processes.values().toArray( new Process[this.processes.size()] );
+    }
+
+    public Package[] getPackages() {
+        return (Package[]) this.pkgs.values().toArray( new Package[this.pkgs.size()] );
+    }
+
+    public Map getPackagesMap() {
+        return this.pkgs;
+    }
+
+    public Map getGlobals() {
+        return this.globals;
+    }
+
+    public Map getAgendaGroupRuleTotals() {
+        return this.agendaGroupRuleTotals;
+    }
+
+    public int getAdditionsSinceLock() {
+        return additionsSinceLock;
+    }
+
+    public int getRemovalsSinceLock() {
+        return removalsSinceLock;
+    }
+
+    public void lock() {
+        this.additionsSinceLock = 0;
+        this.removalsSinceLock = 0;
+
+        this.eventSupport.fireBeforeRuleBaseLocked();
+        this.lock.lock();
+
+        // INVARIANT: lastAquiredLock always contains the index of the last aquired lock +1
+        // in the working memory array
+        this.lastAquiredLock = 0;
+
+        this.wms = getWorkingMemories();
+
+        // Iterate each workingMemory and lock it
+        // This is so we don't update the Rete network during propagation
+        for ( this.lastAquiredLock = 0; this.lastAquiredLock < this.wms.length; this.lastAquiredLock++ ) {
+            this.wms[this.lastAquiredLock].getLock().lock();
+        }
+
+        this.eventSupport.fireAfterRuleBaseLocked();
+    }
+
+    public void unlock() {
+        this.eventSupport.fireBeforeRuleBaseUnlocked();
+
+        // Iterate each workingMemory and attempt to fire any rules, that were activated as a result
+
+        // as per the INVARIANT defined above, we need to iterate from lastAquiredLock-1 to 0.
+        for ( this.lastAquiredLock--; this.lastAquiredLock > -1; this.lastAquiredLock-- ) {
+            this.wms[this.lastAquiredLock].getLock().unlock();
+        }
+
+        this.lock.unlock();
+
+        this.eventSupport.fireAfterRuleBaseUnlocked();
+
+        this.wms = null;
+    }
+
+    /**
+     * Add a <code>Package</code> to the network. Iterates through the
+     * <code>Package</code> adding Each individual <code>Rule</code> to the
+     * network. Before update network each referenced <code>WorkingMemory</code>
+     * is locked.
+     *
+     * @param pkg
+     *            The package to add.
+     * @throws PackageIntegrationException
+     *
+     * @throws RuleIntegrationException
+     *             if an error prevents complete construction of the network for
+     *             the <code>Rule</code>.
+     * @throws FactException
+     * @throws InvalidPatternException
+     */
+    public synchronized void addPackage(final Package newPkg) throws PackageIntegrationException {
+        newPkg.checkValidity();
+        synchronized ( this.pkgs ) {
+            final Package pkg = (Package) this.pkgs.get( newPkg.getName() );
+
+            // only acquire the lock if it hasn't been done explicitely
+            boolean doUnlock = false;
+            if ( !this.lock.isHeldByCurrentThread() && (this.wms == null || this.wms.length == 0) ) {
+                lock();
+                doUnlock = true;
+            }
+            this.additionsSinceLock++;
+
+            this.eventSupport.fireBeforePackageAdded( newPkg );
+
+            if ( pkg != null ) {
+                mergePackage( pkg,
+                              newPkg );
+            } else {
+                this.pkgs.put( newPkg.getName(),
+                               newPkg );
+            }
+
+            final Map newGlobals = newPkg.getGlobals();
+
+            // Check that the global data is valid, we cannot change the type
+            // of an already declared global variable
+            for ( final Iterator it = newGlobals.keySet().iterator(); it.hasNext(); ) {
+                final String identifier = (String) it.next();
+                final Class type = (Class) newGlobals.get( identifier );
+                final boolean f = this.globals.containsKey( identifier );
+                if ( f ) {
+                    final boolean y = !this.globals.get( identifier ).equals( type );
+                    if ( f && y ) {
+                        throw new PackageIntegrationException( pkg );
+                    }
+                }
+            }
+            this.globals.putAll( newGlobals );
+
+            // Add type declarations
+            for ( TypeDeclaration type : newPkg.getTypeDeclarations().values() ) {
+                // should we allow overrides?
+                if ( !this.classTypeDeclaration.containsKey( type.getTypeClass() ) ) {
+                    this.classTypeDeclaration.put( type.getTypeClass(),
+                                                   type );
+                }
+            }
+            
+            final Rule[] rules = newPkg.getRules();
+
+            for ( int i = 0; i < rules.length; ++i ) {
+                addRule( newPkg,
+                         rules[i] );
+            }
+
+            //and now the rule flows
+            if ( newPkg.getRuleFlows() != Collections.EMPTY_MAP ) {
+                final Map flows = newPkg.getRuleFlows();
+                for ( final Iterator iter = flows.entrySet().iterator(); iter.hasNext(); ) {
+                    final Entry flow = (Entry) iter.next();
+                    this.processes.put( flow.getKey(),
+                                        flow.getValue() );
+                }
+            }
+
+            this.packageClassLoader.addClassLoader( newPkg.getPackageCompilationData().getClassLoader() );
+
+            this.eventSupport.fireAfterPackageAdded( newPkg );
+
+            // only unlock if it had been acquired implicitely
+            if ( doUnlock ) {
+                unlock();
+            }
+        }
+
+    }
+
+    /**
+     * Merge a new package with an existing package.
+     * Most of the work is done by the concrete implementations,
+     * but this class does some work (including combining imports, compilation data, globals,
+     * and the actual Rule objects into the package).
+     */
+    private void mergePackage(final Package pkg,
+                              final Package newPkg) throws PackageIntegrationException {
+        final Map globals = pkg.getGlobals();
+        final Map<String, ImportDeclaration> imports = pkg.getImports();
+
+        // First update the binary files
+        // @todo: this probably has issues if you add classes in the incorrect order - functions, rules, invokers.
+        final PackageCompilationData compilationData = pkg.getPackageCompilationData();
+        final PackageCompilationData newCompilationData = newPkg.getPackageCompilationData();
+        final String[] files = newCompilationData.list();
+        for ( int i = 0, length = files.length; i < length; i++ ) {
+            compilationData.write( files[i],
+                                   newCompilationData.read( files[i] ) );
+        }
+
+        // Merge imports
+        imports.putAll( newPkg.getImports() );
+
+        // Add invokers
+        compilationData.putAllInvokers( newCompilationData.getInvokers() );
+
+        if ( compilationData.isDirty() ) {
+            if ( this.reloadPackageCompilationData == null ) {
+                this.reloadPackageCompilationData = new ReloadPackageCompilationData();
+            }
+            this.reloadPackageCompilationData.addPackageCompilationData( compilationData );
+        }
+
+        // Add globals
+        for ( final Iterator it = newPkg.getGlobals().keySet().iterator(); it.hasNext(); ) {
+            final String identifier = (String) it.next();
+            final Class type = (Class) globals.get( identifier );
+            if ( globals.containsKey( identifier ) && !globals.get( identifier ).equals( type ) ) {
+                throw new PackageIntegrationException( "Unable to merge new Package",
+                                                       newPkg );
+            }
+        }
+        globals.putAll( newPkg.getGlobals() );
+
+        // add type declarations
+        for ( TypeDeclaration type : newPkg.getTypeDeclarations().values() ) {
+            // should we allow overrides?
+            if ( !this.classTypeDeclaration.containsKey( type.getTypeClass() ) ) {
+                this.classTypeDeclaration.put( type.getTypeClass(),
+                                               type );
+            }
+            if ( !pkg.getTypeDeclarations().containsKey( type.getTypeName() ) ) {
+                pkg.addTypeDeclaration( type );
+            }
+        }
+        
+        //Add rules into the RuleBase package
+        //as this is needed for individual rule removal later on
+        final Rule[] newRules = newPkg.getRules();
+        for ( int i = 0; i < newRules.length; i++ ) {
+            final Rule newRule = newRules[i];
+            if ( pkg.getRule( newRule.getName() ) == null ) {
+                pkg.addRule( newRule );
+            }
+        }
+
+        //and now the rule flows
+        if ( newPkg.getRuleFlows() != Collections.EMPTY_MAP ) {
+            final Map flows = newPkg.getRuleFlows();
+            for ( final Iterator iter = flows.values().iterator(); iter.hasNext(); ) {
+                final Process flow = (Process) iter.next();
+                pkg.addRuleFlow( flow );
+            }
+        }
+    }
+    
+    public TypeDeclaration getTypeDeclaration(Class< ? > clazz) {
+        return this.classTypeDeclaration.get( clazz );
+    }
+
+    private synchronized void addRule(final Package pkg,
+                                      final Rule rule) throws InvalidPatternException {
+        this.eventSupport.fireBeforeRuleAdded( pkg,
+                                               rule );
+        if ( !rule.isValid() ) {
+            throw new IllegalArgumentException( "The rule called " + rule.getName() + " is not valid. Check for compile errors reported." );
+        }
+        addRule( rule );
+        this.eventSupport.fireAfterRuleAdded( pkg,
+                                              rule );
+    }
+
+    protected abstract void addRule(final Rule rule) throws InvalidPatternException;
+
+    public void removePackage(final String packageName) {
+        synchronized ( this.pkgs ) {
+            final Package pkg = (Package) this.pkgs.get( packageName );
+            if ( pkg == null ) {
+                throw new IllegalArgumentException( "Package name '" + packageName + "' does not exist for this Rule Base." );
+            }
+
+            // only acquire the lock if it hasn't been done explicitely
+            boolean doUnlock = false;
+            if ( !this.lock.isHeldByCurrentThread() && (this.wms == null || this.wms.length == 0) ) {
+                lock();
+                doUnlock = true;
+            }
+            this.removalsSinceLock++;
+
+            this.eventSupport.fireBeforePackageRemoved( pkg );
+
+            final Rule[] rules = pkg.getRules();
+
+            for ( int i = 0; i < rules.length; ++i ) {
+                removeRule( pkg,
+                            rules[i] );
+            }
+
+            this.packageClassLoader.removeClassLoader( pkg.getPackageCompilationData().getClassLoader() );
+
+            // getting the list of referenced globals
+            final Set referencedGlobals = new HashSet();
+            for ( final Iterator it = this.pkgs.values().iterator(); it.hasNext(); ) {
+                final org.drools.rule.Package pkgref = (org.drools.rule.Package) it.next();
+                if ( pkgref != pkg ) {
+                    referencedGlobals.addAll( pkgref.getGlobals().keySet() );
+                }
+            }
+            // removing globals declared inside the package that are not shared
+            for ( final Iterator it = pkg.getGlobals().keySet().iterator(); it.hasNext(); ) {
+                final String globalName = (String) it.next();
+                if ( !referencedGlobals.contains( globalName ) ) {
+                    this.globals.remove( globalName );
+                }
+            }
+            //and now the rule flows
+            final Map flows = pkg.getRuleFlows();
+            for ( final Iterator iter = flows.keySet().iterator(); iter.hasNext(); ) {
+                removeProcess( (String) iter.next() );
+            }
+            // removing the package itself from the list
+            this.pkgs.remove( pkg.getName() );
+
+            //clear all members of the pkg
+            pkg.clear();
+
+            this.eventSupport.fireAfterPackageRemoved( pkg );
+
+            // only unlock if it had been acquired implicitely
+            if ( doUnlock ) {
+                unlock();
+            }
+        }
+    }
+
+    public void removeRule(final String packageName,
+                           final String ruleName) {
+        synchronized ( this.pkgs ) {
+            final Package pkg = (Package) this.pkgs.get( packageName );
+            if ( pkg == null ) {
+                throw new IllegalArgumentException( "Package name '" + packageName + "' does not exist for this Rule Base." );
+            }
+
+            final Rule rule = pkg.getRule( ruleName );
+            if ( rule == null ) {
+                throw new IllegalArgumentException( "Rule name '" + ruleName + "' does not exist in the Package '" + packageName + "'." );
+            }
+
+            // only acquire the lock if it hasn't been done explicitely
+            boolean doUnlock = false;
+            if ( !this.lock.isHeldByCurrentThread() && (this.wms == null || this.wms.length == 0) ) {
+                lock();
+                doUnlock = true;
+            }
+            this.removalsSinceLock++;
+
+            PackageCompilationData compilationData = null;
+
+            removeRule( pkg,
+                        rule );
+            compilationData = pkg.removeRule( rule );
+            if ( this.reloadPackageCompilationData == null ) {
+                this.reloadPackageCompilationData = new ReloadPackageCompilationData();
+            }
+            this.reloadPackageCompilationData.addPackageCompilationData( compilationData );
+
+            // only unlock if it had been acquired implicitely
+            if ( doUnlock ) {
+                unlock();
+            }
+        }
+    }
+
+    private void removeRule(final Package pkg,
+                            final Rule rule) {
+        this.eventSupport.fireBeforeRuleRemoved( pkg,
+                                                 rule );
+        removeRule( rule );
+        this.eventSupport.fireAfterRuleRemoved( pkg,
+                                                rule );
+    }
+
+    protected abstract void removeRule(Rule rule);
+
+    public void removeFunction(final String packageName,
+                               final String functionName) {
+        synchronized ( this.pkgs ) {
+            final Package pkg = (Package) this.pkgs.get( packageName );
+            if ( pkg == null ) {
+                throw new IllegalArgumentException( "Package name '" + packageName + "' does not exist for this Rule Base." );
+            }
+
+            this.eventSupport.fireBeforeFunctionRemoved( pkg,
+                                                         functionName );
+
+            final PackageCompilationData compilationData = pkg.removeFunction( functionName );
+            if ( compilationData == null ) {
+                throw new IllegalArgumentException( "function name '" + packageName + "' does not exist in the Package '" + packageName + "'." );
+            }
+
+            if ( this.reloadPackageCompilationData == null ) {
+                this.reloadPackageCompilationData = new ReloadPackageCompilationData();
+            }
+            this.reloadPackageCompilationData.addPackageCompilationData( compilationData );
+
+            this.eventSupport.fireAfterFunctionRemoved( pkg,
+                                                        functionName );
+        }
+    }
+
+    public synchronized void addProcess(final Process process) {
+        synchronized ( this.pkgs ) {
+            this.processes.put( process.getId(),
+                                process );
+        }
+
+    }
+
+    public synchronized void removeProcess(final String id) {
+        synchronized ( this.pkgs ) {
+            this.processes.remove( id );
+        }
+    }
+
+    public Process getProcess(final String id) {
+        Process process = null;
+        synchronized ( this.pkgs ) {
+            process = (Process) this.processes.get( id );
+        }
+        return process;
+    }
+
+    public Objenesis getObjenesis() {
+        return objenesis;
+    }
+
+    protected synchronized void addStatefulSession(final StatefulSession statefulSession) {
+        this.statefulSessions.add( statefulSession );
+    }
+
+    public Package getPackage(final String name) {
+        return (Package) this.pkgs.get( name );
+    }
+
+    public StatefulSession[] getStatefulSessions() {
+        return (StatefulSession[]) this.statefulSessions.toArray( new StatefulSession[this.statefulSessions.size()] );
+    }
+
+    public InternalWorkingMemory[] getWorkingMemories() {
+        return (InternalWorkingMemory[]) this.statefulSessions.toArray( new InternalWorkingMemory[this.statefulSessions.size()] );
+    }
+
+    public RuleBaseConfiguration getConfiguration() {
+        return this.config;
+    }
+
+    public StatefulSession newStatefulSession(final InputStream stream) throws IOException,
+                                                                       ClassNotFoundException {
+        return newStatefulSession( stream,
+                                   true );
+    }
+
+    public StatefulSession newStatefulSession(final InputStream stream,
+                                              final boolean keepReference) throws IOException,
+                                                                          ClassNotFoundException {
+
+        if ( this.config.isSequential() ) {
+            throw new RuntimeException( "Cannot have a stateful rule session, with sequential configuration set to true" );
+        }
+
+        final DroolsObjectInputStream streamWithLoader = new DroolsObjectInputStream( stream,
+                                                                                      this.packageClassLoader );
+        streamWithLoader.setRuleBase( this );
+
+        final StatefulSession session = (StatefulSession) streamWithLoader.readObject();
+
+        synchronized ( this.pkgs ) {
+            ((InternalWorkingMemory) session).setRuleBase( this );
+            ((InternalWorkingMemory) session).setId( (nextWorkingMemoryCounter()) );
+
+            ExecutorService executor = ExecutorServiceFactory.createExecutorService( this.config.getExecutorService() );
+
+            executor.setCommandExecutor( new CommandExecutor( session ) );
+
+            if ( keepReference ) {
+                addStatefulSession( session );
+                for ( Iterator it = session.getRuleBaseUpdateListeners().iterator(); it.hasNext(); ) {
+                    addEventListener( (RuleBaseEventListener) it.next() );
+                }
+            }
+
+            return (StatefulSession) session;
+        }
+    }
+
+    public void addClass(final String className,
+                         final byte[] bytes) {
+        this.classLoader.addClass( className,
+                                   bytes );
+    }
+
+    public CompositePackageClassLoader getCompositePackageClassLoader() {
+        return this.packageClassLoader;
+    }
+
+    public MapBackedClassLoader getMapBackedClassLoader() {
+        return this.classLoader;
+    }
+
+    public void executeQueuedActions() {
+        synchronized ( this.pkgs ) {
+            if ( this.reloadPackageCompilationData != null ) {
+                this.reloadPackageCompilationData.execute( this );
+                this.reloadPackageCompilationData = null;
+            }
+
+        }
+    }
+
+    public void addEventListener(final RuleBaseEventListener listener) {
+        // since the event support is thread-safe, no need for locks... right?
+        this.eventSupport.addEventListener( listener );
+    }
+
+    public void removeEventListener(final RuleBaseEventListener listener) {
+        // since the event support is thread-safe, no need for locks... right?
+        this.eventSupport.removeEventListener( listener );
+    }
+
+    public List<RuleBaseEventListener> getRuleBaseEventListeners() {
+        // since the event support is thread-safe, no need for locks... right?
+        return this.eventSupport.getEventListeners();
+    }
+
+    public boolean isEvent(Class clazz) {
+        for ( Package pkg : this.pkgs.values() ) {
+            if ( pkg.isEvent( clazz ) ) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static class ReloadPackageCompilationData
+        implements
+        RuleBaseAction {
+        private static final long serialVersionUID = 1L;
+        private Set               set;
+
+        public void addPackageCompilationData(final PackageCompilationData packageCompilationData) {
+            if ( this.set == null ) {
+                this.set = new HashSet();
+            }
+
+            this.set.add( packageCompilationData );
+        }
+
+        public void execute(final InternalRuleBase ruleBase) {
+            for ( final Iterator it = this.set.iterator(); it.hasNext(); ) {
+                final PackageCompilationData packageCompilationData = (PackageCompilationData) it.next();
+                packageCompilationData.reload();
+            }
+        }
+    }
+
+    public static interface RuleBaseAction
+        extends
+        Serializable {
+        public void execute(InternalRuleBase ruleBase);
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/AbstractWorkingMemory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/AbstractWorkingMemory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/AbstractWorkingMemory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,1678 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.drools.Agenda;
+import org.drools.EntryPointInterface;
+import org.drools.FactException;
+import org.drools.FactHandle;
+import org.drools.ObjectFilter;
+import org.drools.Otherwise;
+import org.drools.QueryResults;
+import org.drools.RuleBase;
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuntimeDroolsException;
+import org.drools.WorkingMemory;
+import org.drools.RuleBaseConfiguration.AssertBehaviour;
+import org.drools.RuleBaseConfiguration.LogicalOverride;
+import org.drools.base.MapGlobalResolver;
+import org.drools.base.ShadowProxy;
+import org.drools.event.AgendaEventListener;
+import org.drools.event.AgendaEventSupport;
+import org.drools.event.RuleBaseEventListener;
+import org.drools.event.RuleFlowEventListener;
+import org.drools.event.RuleFlowEventSupport;
+import org.drools.event.WorkingMemoryEventListener;
+import org.drools.event.WorkingMemoryEventSupport;
+import org.drools.facttemplates.Fact;
+import org.drools.process.core.Process;
+import org.drools.process.instance.ProcessInstance;
+import org.drools.process.instance.ProcessInstanceFactory;
+import org.drools.process.instance.WorkItemManager;
+import org.drools.reteoo.ClassObjectTypeConf;
+import org.drools.reteoo.FactTemplateTypeConf;
+import org.drools.reteoo.LIANodePropagation;
+import org.drools.reteoo.ObjectTypeConf;
+import org.drools.rule.Declaration;
+import org.drools.rule.EntryPoint;
+import org.drools.rule.Rule;
+import org.drools.rule.TimeMachine;
+import org.drools.ruleflow.core.RuleFlowProcess;
+import org.drools.ruleflow.instance.RuleFlowProcessInstanceFactory;
+import org.drools.spi.Activation;
+import org.drools.spi.AgendaFilter;
+import org.drools.spi.AgendaGroup;
+import org.drools.spi.AsyncExceptionHandler;
+import org.drools.spi.FactHandleFactory;
+import org.drools.spi.GlobalResolver;
+import org.drools.spi.PropagationContext;
+import org.drools.temporal.SessionClock;
+
+/**
+ * Implementation of <code>WorkingMemory</code>.
+ * 
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter </a>
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris </a>
+ */
+public abstract class AbstractWorkingMemory
+    implements
+    InternalWorkingMemoryActions,
+    EventSupport,
+    PropertyChangeListener {
+    // ------------------------------------------------------------
+    // Constants
+    // ------------------------------------------------------------
+    protected static final Class[]                       ADD_REMOVE_PROPERTY_CHANGE_LISTENER_ARG_TYPES = new Class[]{PropertyChangeListener.class};
+    private static final int                             NODE_MEMORIES_ARRAY_GROWTH                    = 32;
+
+    // ------------------------------------------------------------
+    // Instance members
+    // ------------------------------------------------------------
+    protected long                                       id;
+
+    /** The arguments used when adding/removing a property change listener. */
+    protected final Object[]                             addRemovePropertyChangeListenerArgs           = new Object[]{this};
+
+    /** The actual memory for the <code>JoinNode</code>s. */
+    protected final NodeMemories                         nodeMemories;
+
+    
+    protected final ObjectStore                          objectStore;
+
+    protected Map                                        queryResults                                  = Collections.EMPTY_MAP;
+
+    /** Global values which are associated with this memory. */
+    protected GlobalResolver                             globalResolver;
+
+    protected static final Object                        NULL                                          = new Serializable() {
+                                                                                                           private static final long serialVersionUID = 400L;
+                                                                                                       };
+
+    /** The eventSupport */
+    protected WorkingMemoryEventSupport                  workingMemoryEventSupport                     = new WorkingMemoryEventSupport();
+
+    protected AgendaEventSupport                         agendaEventSupport                            = new AgendaEventSupport();
+
+    protected RuleFlowEventSupport                workflowEventSupport                          = new RuleFlowEventSupport();
+    
+    protected List                                  __ruleBaseEventListeners                      = new LinkedList();                      
+
+    /** The <code>RuleBase</code> with which this memory is associated. */
+    protected transient InternalRuleBase                 ruleBase;
+
+    protected final FactHandleFactory                    handleFactory;
+
+    protected final TruthMaintenanceSystem               tms;
+
+    /** Rule-firing agenda. */
+    protected DefaultAgenda                              agenda;
+
+    protected final List                                 actionQueue                                   = new ArrayList();
+
+    protected final ReentrantLock                        lock                                          = new ReentrantLock();
+
+    protected final boolean                              discardOnLogicalOverride;
+
+    protected long                                       propagationIdCounter;
+
+    private final boolean                                maintainTms;
+
+    private final boolean                                sequential;
+
+    private List                                         liaPropagations                               = Collections.EMPTY_LIST;
+
+    /** Flag to determine if a rule is currently being fired. */
+    protected boolean                                    firing;
+
+    protected boolean                                    halt;
+
+    private Map                                          processInstances                              = new HashMap();
+
+    private int                                          processCounter;
+
+    private WorkItemManager                              workItemManager;
+    
+    private Map<String, ProcessInstanceFactory>          processInstanceFactories                      = new HashMap();
+
+    private TimeMachine                                  timeMachine                                   = new TimeMachine();
+
+    private Map<EntryPoint, Map<Object, ObjectTypeConf>> typeConfMap;
+
+    //private SessionClock                                 sessionClock;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    /**
+     * Construct.
+     * 
+     * @param ruleBase
+     *            The backing rule-base.
+     */
+    public AbstractWorkingMemory(final int id,
+                                 final InternalRuleBase ruleBase,
+                                 final FactHandleFactory handleFactory) {
+        this.id = id;
+        this.ruleBase = ruleBase;
+        this.handleFactory = handleFactory;
+        this.globalResolver = new MapGlobalResolver();
+        this.maintainTms = this.ruleBase.getConfiguration().isMaintainTms();
+        this.sequential = this.ruleBase.getConfiguration().isSequential();
+        
+        this.nodeMemories = new ConcurrentNodeMemories( this.ruleBase );
+
+        if ( this.maintainTms ) {
+            this.tms = new TruthMaintenanceSystem( this );
+        } else {
+            this.tms = null;
+        }
+        
+        final RuleBaseConfiguration conf = this.ruleBase.getConfiguration();
+        
+        this.objectStore = new SingleThreadedObjectStore(conf, this.lock);        
+
+        // Only takes effect if are using idententity behaviour for assert
+        if ( conf.getLogicalOverride() == LogicalOverride.DISCARD ) {
+            this.discardOnLogicalOverride = true;
+        } else {
+            this.discardOnLogicalOverride = false;
+        }
+
+        this.workItemManager = new WorkItemManager( this );
+        this.processInstanceFactories.put(
+            RuleFlowProcess.RULEFLOW_TYPE, new RuleFlowProcessInstanceFactory());
+
+        this.typeConfMap = new HashMap<EntryPoint, Map<Object, ObjectTypeConf>>();
+    }
+
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+
+    public void setRuleBase(final InternalRuleBase ruleBase) {
+        this.ruleBase = ruleBase;
+        this.nodeMemories.setRuleBaseReference( this.ruleBase );
+    }
+
+    public void setWorkingMemoryEventSupport(WorkingMemoryEventSupport workingMemoryEventSupport) {
+        this.workingMemoryEventSupport = workingMemoryEventSupport;
+    }
+
+    public void setAgendaEventSupport(AgendaEventSupport agendaEventSupport) {
+        this.agendaEventSupport = agendaEventSupport;
+    }
+
+    public void setRuleFlowEventSupport(RuleFlowEventSupport ruleFlowEventSupport) {
+        this.workflowEventSupport = ruleFlowEventSupport;
+    }
+
+    public boolean isSequential() {
+        return this.sequential;
+    }
+
+    public void addLIANodePropagation(LIANodePropagation liaNodePropagation) {
+        if ( this.liaPropagations == Collections.EMPTY_LIST ) {
+            this.liaPropagations = new ArrayList();
+        }
+        this.liaPropagations.add( liaNodePropagation );
+    }
+
+    public void addEventListener(final WorkingMemoryEventListener listener) {
+        this.workingMemoryEventSupport.addEventListener( listener );
+    }
+
+    public void removeEventListener(final WorkingMemoryEventListener listener) {
+        this.workingMemoryEventSupport.removeEventListener( listener );
+    }
+
+    public List getWorkingMemoryEventListeners() {
+        return this.workingMemoryEventSupport.getEventListeners();
+    }
+
+    public void addEventListener(final AgendaEventListener listener) {
+        this.agendaEventSupport.addEventListener( listener );
+    }
+
+    public void removeEventListener(final AgendaEventListener listener) {
+        this.agendaEventSupport.removeEventListener( listener );
+    }
+
+    public List getAgendaEventListeners() {
+        return this.agendaEventSupport.getEventListeners();
+    }
+
+    public void addEventListener(final RuleFlowEventListener listener) {
+        this.workflowEventSupport.addEventListener( listener );
+    }
+
+    public void removeEventListener(final RuleFlowEventListener listener) {
+        this.workflowEventSupport.removeEventListener( listener );
+    }
+
+    public List getRuleFlowEventListeners() {
+        return this.workflowEventSupport.getEventListeners();
+    }
+
+    public void addEventListener(RuleBaseEventListener listener) {
+        this.ruleBase.addEventListener( listener );
+        this.__ruleBaseEventListeners.add( listener );
+    }
+
+    public List getRuleBaseEventListeners() {
+        return Collections.unmodifiableList( this.__ruleBaseEventListeners );
+    }
+
+    public void removeEventListener(RuleBaseEventListener listener) {
+        this.ruleBase.removeEventListener( listener );
+        this.__ruleBaseEventListeners.remove( listener );
+    }
+
+    public FactHandleFactory getFactHandleFactory() {
+        return this.handleFactory;
+    }
+
+    public void setGlobal(final String identifier,
+                          final Object value) {
+        // Cannot set null values
+        if ( value == null ) {
+            return;
+        }
+
+        try {
+            this.lock.lock();
+            // Make sure the global has been declared in the RuleBase
+            final Map globalDefintions = this.ruleBase.getGlobals();
+            final Class type = (Class) globalDefintions.get( identifier );
+            if ( (type == null) ) {
+                throw new RuntimeException( "Unexpected global [" + identifier + "]" );
+            } else if ( !type.isInstance( value ) ) {
+                throw new RuntimeException( "Illegal class for global. " + "Expected [" + type.getName() + "], " + "found [" + value.getClass().getName() + "]." );
+
+            } else {
+                this.globalResolver.setGlobal( identifier,
+                                               value );
+            }
+        } finally {
+            this.lock.unlock();
+        }
+    }
+
+    public void setGlobalResolver(final GlobalResolver globalResolver) {
+        try {
+            this.lock.lock();
+            this.globalResolver = globalResolver;
+        } finally {
+            this.lock.unlock();
+        }
+    }
+
+    public GlobalResolver getGlobalResolver() {
+        return this.globalResolver;
+    }
+
+    public long getId() {
+        return this.id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public Object getGlobal(final String identifier) {
+        try {
+            this.lock.lock();
+            return this.globalResolver.resolveGlobal( identifier );
+        } finally {
+            this.lock.unlock();
+        }
+    }
+
+    public Agenda getAgenda() {
+        return this.agenda;
+    }
+
+    public void clearAgenda() {
+        this.agenda.clearAgenda();
+    }
+
+    public void clearAgendaGroup(final String group) {
+        this.agenda.clearAgendaGroup( group );
+    }
+
+    public void clearActivationGroup(final String group) {
+        this.agenda.clearActivationGroup( group );
+    }
+
+    public void clearRuleFlowGroup(final String group) {
+        this.agenda.clearRuleFlowGroup( group );
+    }
+
+    public RuleBase getRuleBase() {
+        return this.ruleBase;
+    }
+
+    public void halt() {
+        this.halt = true;
+    }
+
+    public synchronized void fireAllRules() throws FactException {
+        fireAllRules( null,
+                      -1 );
+    }
+
+    public synchronized void fireAllRules(int fireLimit) throws FactException {
+        fireAllRules( null,
+                      fireLimit );
+    }
+
+    public synchronized void fireAllRules(final AgendaFilter agendaFilter) throws FactException {
+        fireAllRules( agendaFilter,
+                      -1 );
+    }
+
+    public synchronized void fireAllRules(final AgendaFilter agendaFilter,
+                                          int fireLimit) throws FactException {
+        // If we're already firing a rule, then it'll pick up
+        // the firing for any other assertObject(..) that get
+        // nested inside, avoiding concurrent-modification
+        // exceptions, depending on code paths of the actions.
+        this.halt = false;
+
+        if ( isSequential() ) {
+            for ( Iterator it = this.liaPropagations.iterator(); it.hasNext(); ) {
+                ((LIANodePropagation) it.next()).doPropagation( this );
+            }
+        }
+
+        if ( !this.actionQueue.isEmpty() ) {
+            executeQueuedActions();
+        }
+
+        boolean noneFired = true;
+
+        if ( !this.firing ) {
+            try {
+                this.firing = true;
+
+                while ( continueFiring( fireLimit ) && this.agenda.fireNextItem( agendaFilter ) ) {
+                    fireLimit = updateFireLimit( fireLimit );
+                    noneFired = false;
+                    if ( !this.actionQueue.isEmpty() ) {
+                        executeQueuedActions();
+                    }
+                }
+            } finally {
+                this.firing = false;
+                // @todo (mproctor) disabling Otherwise management for now, not
+                // happy with the current implementation
+                // if ( noneFired ) {
+                // doOtherwise( agendaFilter,
+                // fireLimit );
+                // }
+
+            }
+        }
+    }
+
+    private final boolean continueFiring(final int fireLimit) {
+        return (!halt) && (fireLimit != 0);
+    }
+
+    private final int updateFireLimit(final int fireLimit) {
+        return fireLimit > 0 ? fireLimit - 1 : fireLimit;
+    }
+
+    /**
+     * This does the "otherwise" phase of processing. If no items are fired,
+     * then it will assert a temporary "Otherwise" fact and allow any rules to
+     * fire to handle "otherwise" cases.
+     */
+    private void doOtherwise(final AgendaFilter agendaFilter,
+                             int fireLimit) {
+        final FactHandle handle = this.insert( new Otherwise() );
+        if ( !this.actionQueue.isEmpty() ) {
+            executeQueuedActions();
+        }
+
+        while ( continueFiring( fireLimit ) && this.agenda.fireNextItem( agendaFilter ) ) {
+            fireLimit = updateFireLimit( fireLimit );
+        }
+
+        this.retract( handle );
+    }
+
+    //
+    // MN: The following is the traditional fireAllRules (without otherwise).
+    // Purely kept here as this implementation of otherwise is still
+    // experimental.
+    //
+    // public synchronized void fireAllRules(final AgendaFilter agendaFilter)
+    // throws FactException {
+    // // If we're already firing a rule, then it'll pick up
+    // // the firing for any other assertObject(..) that get
+    // // nested inside, avoiding concurrent-modification
+    // // exceptions, depending on code paths of the actions.
+    //
+    // if ( !this.factQueue.isEmpty() ) {
+    // propagateQueuedActions();
+    // }
+    //
+    // if ( !this.firing ) {
+    // try {
+    // this.firing = true;
+    //
+    // while ( this.agenda.fireNextItem( agendaFilter ) ) {
+    // ;
+    // }
+    // } finally {
+    // this.firing = false;
+    // }
+    // }
+    // }
+
+    /**
+     * Returns the fact Object for the given <code>FactHandle</code>. It
+     * actually attemps to return the value from the handle, before retrieving
+     * it from objects map.
+     * 
+     * @see WorkingMemory
+     * 
+     * @param handle
+     *            The <code>FactHandle</code> reference for the
+     *            <code>Object</code> lookup
+     * 
+     */
+    public Object getObject(final FactHandle handle) {
+        return this.objectStore.getObjectForHandle( (InternalFactHandle) handle );
+    }
+    
+    public ObjectStore getObjectStore() {
+        return this.objectStore;
+    }
+
+    /**
+     * @see WorkingMemory
+     */
+    public FactHandle getFactHandle(final Object object) {
+        return this.objectStore.getHandleForObject( object );
+    }
+    
+    /**
+     * @see WorkingMemory
+     */
+    public FactHandle getFactHandleByIdentity(final Object object) {
+        return this.objectStore.getHandleForObjectIdentity( object );
+    }
+
+    /**
+     * This class is not thread safe, changes to the working memory during
+     * iteration may give unexpected results
+     */
+    public Iterator iterateObjects() {
+        return this.objectStore.iterateObjects( );
+    }
+
+    /**
+     * This class is not thread safe, changes to the working memory during
+     * iteration may give unexpected results
+     */
+    public Iterator iterateObjects(ObjectFilter filter) {
+        return this.objectStore.iterateObjects( filter );
+    }
+
+    /**
+     * This class is not thread safe, changes to the working memory during
+     * iteration may give unexpected results
+     */
+    public Iterator iterateFactHandles() {
+        return this.objectStore.iterateFactHandles();
+    }
+
+    /**
+     * This class is not thread safe, changes to the working memory during
+     * iteration may give unexpected results
+     */
+    public Iterator iterateFactHandles(ObjectFilter filter) {
+        return this.objectStore.iterateFactHandles( filter );
+    }
+
+    public abstract QueryResults getQueryResults(String query);
+
+    public AgendaGroup getFocus() {
+        return this.agenda.getFocus();
+    }
+
+    public void setFocus(final String focus) {
+        this.agenda.setFocus( focus );
+    }
+
+    public void setFocus(final AgendaGroup focus) {
+        this.agenda.setFocus( focus );
+    }
+
+    public TruthMaintenanceSystem getTruthMaintenanceSystem() {
+        return this.tms;
+    }
+
+    /**
+     * @see WorkingMemory
+     */
+    public FactHandle insert(final Object object) throws FactException {
+        return insert( object, /* Not-Dynamic */
+                       false,
+                       false,
+                       null,
+                       null );
+    }
+
+    /**
+     * @see WorkingMemory
+     */
+    public FactHandle insertLogical(final Object object) throws FactException {
+        return insert( object, //Not-Dynamic 
+                       false,
+                       true,
+                       null,
+                       null );
+    }
+
+    public FactHandle insert(final Object object,
+                             final boolean dynamic) throws FactException {
+        return insert( object,
+                       dynamic,
+                       false,
+                       null,
+                       null );
+    }
+
+    public FactHandle insertLogical(final Object object,
+                                    final boolean dynamic) throws FactException {
+        return insert( object,
+                       dynamic,
+                       true,
+                       null,
+                       null );
+    }
+
+    public FactHandle insert(final Object object,
+                             final boolean dynamic,
+                             boolean logical,
+                             final Rule rule,
+                             final Activation activation) throws FactException {
+        return this.insert( EntryPoint.DEFAULT,
+                            object,
+                            dynamic,
+                            logical,
+                            rule,
+                            activation );
+
+    }
+
+    protected FactHandle insert(final EntryPoint entryPoint,
+                                final Object object,
+                                final boolean dynamic,
+                                boolean logical,
+                                final Rule rule,
+                                final Activation activation) throws FactException {
+        if ( object == null ) {
+            // you cannot assert a null object
+            return null;
+        }
+
+        ObjectTypeConf typeConf = getObjectTypeConf( entryPoint,
+                                                     object );
+
+        InternalFactHandle handle = null;
+
+        if ( isSequential() ) {
+            handle = this.handleFactory.newFactHandle( object,
+                                                       typeConf.isEvent(),
+                                                       this );
+            this.objectStore.addHandle( handle, object );
+            insert( entryPoint,
+                    handle,
+                    object,
+                    rule,
+                    activation );
+            return handle;
+        }
+
+        try {
+            this.lock.lock();
+            // check if the object already exists in the WM
+            handle = (InternalFactHandle) this.objectStore.getHandleForObject(object);
+
+            if ( this.maintainTms ) {
+
+                EqualityKey key = null;
+
+                if ( handle == null ) {
+                    // lets see if the object is already logical asserted
+                    key = this.tms.get( object );
+                } else {
+                    // Object is already asserted, so check and possibly correct
+                    // its
+                    // status and then return the handle
+                    key = handle.getEqualityKey();
+
+                    if ( key.getStatus() == EqualityKey.STATED ) {
+                        // return null as you cannot justify a stated object.
+                        return handle;
+                    }
+
+                    if ( !logical ) {
+                        // this object was previously justified, so we have to
+                        // override it to stated
+                        key.setStatus( EqualityKey.STATED );
+                        this.tms.removeLogicalDependencies( handle );
+                    } else {
+                        // this was object is already justified, so just add new
+                        // logical dependency
+                        this.tms.addLogicalDependency( handle,
+                                                       activation,
+                                                       activation.getPropagationContext(),
+                                                       rule );
+                    }
+
+                    return handle;
+                }
+
+                // At this point we know the handle is null
+                if ( key == null ) {
+                    // key is also null, so treat as a totally new
+                    // stated/logical
+                    // assert
+                    handle = this.handleFactory.newFactHandle( object,
+                                                               typeConf.isEvent(),
+                                                               this );
+                    this.objectStore.addHandle( handle, object );
+
+                    key = new EqualityKey( handle );
+                    handle.setEqualityKey( key );
+                    this.tms.put( key );
+                    if ( !logical ) {
+                        key.setStatus( EqualityKey.STATED );
+                    } else {
+                        key.setStatus( EqualityKey.JUSTIFIED );
+                        this.tms.addLogicalDependency( handle,
+                                                       activation,
+                                                       activation.getPropagationContext(),
+                                                       rule );
+                    }
+                } else if ( !logical ) {
+                    if ( key.getStatus() == EqualityKey.JUSTIFIED ) {
+                        // Its previous justified, so switch to stated and
+                        // remove
+                        // logical dependencies
+                        final InternalFactHandle justifiedHandle = key.getFactHandle();
+                        this.tms.removeLogicalDependencies( justifiedHandle );
+
+                        if ( this.discardOnLogicalOverride ) {
+                            // override, setting to new instance, and return
+                            // existing handle
+                            key.setStatus( EqualityKey.STATED );
+                            handle = key.getFactHandle();
+
+                            if ( this.ruleBase.getConfiguration().getAssertBehaviour() == AssertBehaviour.IDENTITY ) {
+                                // as assertMap may be using an "identity"
+                                // equality comparator,
+                                // we need to remove the handle from the map,
+                                // before replacing the object
+                                // and then re-add the handle. Otherwise we may
+                                // end up with a leak.
+                                this.objectStore.updateHandle( handle, object );
+                            } else {
+                                Object oldObject = handle.getObject();
+                                if ( oldObject instanceof ShadowProxy ) {
+                                    ((ShadowProxy) oldObject).setShadowedObject( object );
+                                } else {
+                                    handle.setObject( object );
+                                }
+                            }
+                            return handle;
+                        } else {
+                            // override, then instantiate new handle for
+                            // assertion
+                            key.setStatus( EqualityKey.STATED );
+                            handle = this.handleFactory.newFactHandle( object,
+                                                                       typeConf.isEvent(),
+                                                                       this );
+                            handle.setEqualityKey( key );
+                            key.addFactHandle( handle );
+                            this.objectStore.addHandle( handle, object );
+
+                        }
+
+                    } else {
+                        handle = this.handleFactory.newFactHandle( object,
+                                                                   typeConf.isEvent(),
+                                                                   this );
+                        this.objectStore.addHandle( handle, object );
+                        key.addFactHandle( handle );
+                        handle.setEqualityKey( key );
+
+                    }
+
+                } else {
+                    if ( key.getStatus() == EqualityKey.JUSTIFIED ) {
+                        // only add as logical dependency if this wasn't
+                        // previously
+                        // stated
+                        this.tms.addLogicalDependency( key.getFactHandle(),
+                                                       activation,
+                                                       activation.getPropagationContext(),
+                                                       rule );
+                        return key.getFactHandle();
+                    } else {
+                        // You cannot justify a previously stated equality equal
+                        // object, so return null
+                        return null;
+                    }
+                }
+
+            } else {
+                if ( handle != null ) {
+                    return handle;
+                }
+                handle = this.handleFactory.newFactHandle( object,
+                                                           typeConf.isEvent(),
+                                                           this );
+                this.objectStore.addHandle( handle, object );
+
+            }
+
+            if ( dynamic ) {
+                addPropertyChangeListener( object );
+            }
+
+            insert( entryPoint,
+                    handle,
+                    object,
+                    rule,
+                    activation );
+
+        } finally {
+            this.lock.unlock();
+        }
+        return handle;
+    }
+
+    protected void insert(final EntryPoint entryPoint,
+                          final InternalFactHandle handle,
+                          final Object object,
+                          final Rule rule,
+                          final Activation activation) {
+        this.ruleBase.executeQueuedActions();
+
+        if ( activation != null ) {
+            // release resources so that they can be GC'ed
+            activation.getPropagationContext().releaseResources();
+        }
+        final PropagationContext propagationContext = new PropagationContextImpl( this.propagationIdCounter++,
+                                                                                  PropagationContext.ASSERTION,
+                                                                                  rule,
+                                                                                  activation,
+                                                                                  this.agenda.getActiveActivations(),
+                                                                                  this.agenda.getDormantActivations(),
+                                                                                  entryPoint );
+
+        doInsert( handle,
+                  object,
+                  propagationContext );
+
+        if ( !this.actionQueue.isEmpty() ) {
+            executeQueuedActions();
+        }
+
+        this.workingMemoryEventSupport.fireObjectInserted( propagationContext,
+                                                           handle,
+                                                           object,
+                                                           this );
+    }
+
+    protected void addPropertyChangeListener(final Object object) {
+        try {
+            final Method method = object.getClass().getMethod( "addPropertyChangeListener",
+                                                               AbstractWorkingMemory.ADD_REMOVE_PROPERTY_CHANGE_LISTENER_ARG_TYPES );
+
+            method.invoke( object,
+                           this.addRemovePropertyChangeListenerArgs );
+        } catch ( final NoSuchMethodException e ) {
+            System.err.println( "Warning: Method addPropertyChangeListener not found" + " on the class " + object.getClass() + " so Drools will be unable to process JavaBean" + " PropertyChangeEvents on the asserted Object" );
+        } catch ( final IllegalArgumentException e ) {
+            System.err.println( "Warning: The addPropertyChangeListener method" + " on the class " + object.getClass() + " does not take" + " a simple PropertyChangeListener argument" + " so Drools will be unable to process JavaBean"
+                                + " PropertyChangeEvents on the asserted Object" );
+        } catch ( final IllegalAccessException e ) {
+            System.err.println( "Warning: The addPropertyChangeListener method" + " on the class " + object.getClass() + " is not public" + " so Drools will be unable to process JavaBean" + " PropertyChangeEvents on the asserted Object" );
+        } catch ( final InvocationTargetException e ) {
+            System.err.println( "Warning: The addPropertyChangeListener method" + " on the class " + object.getClass() + " threw an InvocationTargetException" + " so Drools will be unable to process JavaBean"
+                                + " PropertyChangeEvents on the asserted Object: " + e.getMessage() );
+        } catch ( final SecurityException e ) {
+            System.err.println( "Warning: The SecurityManager controlling the class " + object.getClass() + " did not allow the lookup of a" + " addPropertyChangeListener method" + " so Drools will be unable to process JavaBean"
+                                + " PropertyChangeEvents on the asserted Object: " + e.getMessage() );
+        }
+    }
+
+    public abstract void doInsert(InternalFactHandle factHandle,
+                                  Object object,
+                                  PropagationContext propagationContext) throws FactException;
+
+    protected void removePropertyChangeListener(final FactHandle handle) {
+        Object object = null;
+        try {
+            object = getObject( handle );
+
+            if ( object != null ) {
+                final Method mehod = object.getClass().getMethod( "removePropertyChangeListener",
+                                                                  AbstractWorkingMemory.ADD_REMOVE_PROPERTY_CHANGE_LISTENER_ARG_TYPES );
+
+                mehod.invoke( object,
+                              this.addRemovePropertyChangeListenerArgs );
+            }
+        } catch ( final NoSuchMethodException e ) {
+            // The removePropertyChangeListener method on the class
+            // was not found so Drools will be unable to
+            // stop processing JavaBean PropertyChangeEvents
+            // on the retracted Object
+        } catch ( final IllegalArgumentException e ) {
+            throw new RuntimeDroolsException( "Warning: The removePropertyChangeListener method on the class " + object.getClass() + " does not take a simple PropertyChangeListener argument so Drools will be unable to stop processing JavaBean"
+                                              + " PropertyChangeEvents on the retracted Object" );
+        } catch ( final IllegalAccessException e ) {
+            throw new RuntimeDroolsException( "Warning: The removePropertyChangeListener method on the class " + object.getClass() + " is not public so Drools will be unable to stop processing JavaBean PropertyChangeEvents on the retracted Object" );
+        } catch ( final InvocationTargetException e ) {
+            throw new RuntimeDroolsException( "Warning: The removePropertyChangeL istener method on the class " + object.getClass() + " threw an InvocationTargetException so Drools will be unable to stop processing JavaBean"
+                                              + " PropertyChangeEvents on the retracted Object: " + e.getMessage() );
+        } catch ( final SecurityException e ) {
+            throw new RuntimeDroolsException( "Warning: The SecurityManager controlling the class " + object.getClass() + " did not allow the lookup of a removePropertyChangeListener method so Drools will be unable to stop processing JavaBean"
+                                              + " PropertyChangeEvents on the retracted Object: " + e.getMessage() );
+        }
+    }
+
+    public void retract(final FactHandle handle) throws FactException {
+        retract( handle,
+                 true,
+                 true,
+                 null,
+                 null );
+    }
+
+    public abstract void doRetract(InternalFactHandle factHandle,
+                                   PropagationContext propagationContext);
+
+    /**
+     * @see WorkingMemory
+     */
+    public void retract(final FactHandle factHandle,
+                        final boolean removeLogical,
+                        final boolean updateEqualsMap,
+                        final Rule rule,
+                        final Activation activation) throws FactException {
+        this.retract( EntryPoint.DEFAULT,
+                      factHandle,
+                      removeLogical,
+                      updateEqualsMap,
+                      rule,
+                      activation );
+
+    }
+
+    protected void retract(final EntryPoint entryPoint,
+                           final FactHandle factHandle,
+                           final boolean removeLogical,
+                           final boolean updateEqualsMap,
+                           final Rule rule,
+                           final Activation activation) throws FactException {
+        try {
+            this.lock.lock();
+            this.ruleBase.executeQueuedActions();
+
+            final InternalFactHandle handle = (InternalFactHandle) factHandle;
+            if ( handle.getId() == -1 ) {
+                // can't retract an already retracted handle
+                return;
+            }
+            removePropertyChangeListener( handle );
+
+            if ( activation != null ) {
+                // release resources so that they can be GC'ed
+                activation.getPropagationContext().releaseResources();
+            }
+            final PropagationContext propagationContext = new PropagationContextImpl( this.propagationIdCounter++,
+                                                                                      PropagationContext.RETRACTION,
+                                                                                      rule,
+                                                                                      activation,
+                                                                                      this.agenda.getActiveActivations(),
+                                                                                      this.agenda.getDormantActivations(),
+                                                                                      entryPoint );
+
+            doRetract( handle,
+                       propagationContext );
+
+            if ( this.maintainTms ) {
+                // Update the equality key, which maintains a list of stated
+                // FactHandles
+                final EqualityKey key = handle.getEqualityKey();
+
+                // Its justified so attempt to remove any logical dependencies
+                // for
+                // the handle
+                if ( key.getStatus() == EqualityKey.JUSTIFIED ) {
+                    this.tms.removeLogicalDependencies( handle );
+                }
+
+                key.removeFactHandle( handle );
+                handle.setEqualityKey( null );
+
+                // If the equality key is now empty, then remove it
+                if ( key.isEmpty() ) {
+                    this.tms.remove( key );
+                }
+            }
+
+            final Object object = handle.getObject();
+
+            this.workingMemoryEventSupport.fireObjectRetracted( propagationContext,
+                                                                handle,
+                                                                object,
+                                                                this );
+
+            this.objectStore.removeHandle( handle );
+
+            this.handleFactory.destroyFactHandle( handle );
+
+            if ( !this.actionQueue.isEmpty() ) {
+                executeQueuedActions();
+            }
+        } finally {
+            this.lock.unlock();
+        }
+    }
+
+//    private void addHandleToMaps(InternalFactHandle handle) {
+//        this.assertMap.put( handle,
+//                            handle,
+//                            false );
+//        if ( this.ruleBase.getConfiguration().getAssertBehaviour() == AssertBehaviour.EQUALITY ) {
+//            this.identityMap.put( handle,
+//                                  handle,
+//                                  false );
+//        }
+//    }
+//
+//    private void removeHandleFromMaps(final InternalFactHandle handle) {
+//        this.assertMap.remove( handle );
+//        if ( this.ruleBase.getConfiguration().getAssertBehaviour() == AssertBehaviour.EQUALITY ) {
+//            this.identityMap.remove( handle );
+//        }
+//    }
+
+    public void modifyRetract(final FactHandle factHandle) {
+        modifyRetract( factHandle,
+                       null,
+                       null );
+    }
+
+    public void modifyRetract(final FactHandle factHandle,
+                              final Rule rule,
+                              final Activation activation) {
+        this.modifyRetract( EntryPoint.DEFAULT,
+                            factHandle,
+                            rule,
+                            activation );
+    }
+
+    protected void modifyRetract(final EntryPoint entryPoint,
+                                 final FactHandle factHandle,
+                                 final Rule rule,
+                                 final Activation activation) {
+        try {
+            this.lock.lock();
+            this.ruleBase.executeQueuedActions();
+
+            // only needed if we maintain tms, but either way we must get it
+            // before we do the retract
+            int status = -1;
+            if ( this.maintainTms ) {
+                status = ((InternalFactHandle) factHandle).getEqualityKey().getStatus();
+            }
+            final InternalFactHandle handle = (InternalFactHandle) factHandle;
+            // final Object originalObject = (handle.isShadowFact()) ?
+            // ((ShadowProxy) handle.getObject()).getShadowedObject() :
+            // handle.getObject();
+
+            if ( handle.getId() == -1 ) {
+                // the handle is invalid, most likely already retracted, so
+                // return
+                return;
+            }
+
+            if ( activation != null ) {
+                // release resources so that they can be GC'ed
+                activation.getPropagationContext().releaseResources();
+            }
+            // Nowretract any trace of the original fact
+            final PropagationContext propagationContext = new PropagationContextImpl( this.propagationIdCounter++,
+                                                                                      PropagationContext.MODIFICATION,
+                                                                                      rule,
+                                                                                      activation,
+                                                                                      this.agenda.getActiveActivations(),
+                                                                                      this.agenda.getDormantActivations(),
+                                                                                      entryPoint );
+            doRetract( handle,
+                       propagationContext );
+
+            if ( this.maintainTms ) {
+
+                // the hashCode and equality has changed, so we must update the
+                // EqualityKey
+                EqualityKey key = handle.getEqualityKey();
+                key.removeFactHandle( handle );
+
+                // If the equality key is now empty, then remove it
+                if ( key.isEmpty() ) {
+                    this.tms.remove( key );
+                }
+            }
+        } finally {
+            this.lock.unlock();
+        }
+    }
+
+    public void modifyInsert(final FactHandle factHandle,
+                             final Object object) {
+        modifyInsert( factHandle,
+                      object,
+                      null,
+                      null );
+    }
+
+    public void modifyInsert(final FactHandle factHandle,
+                             final Object object,
+                             final Rule rule,
+                             final Activation activation) {
+        this.modifyInsert( EntryPoint.DEFAULT,
+                           factHandle,
+                           object,
+                           rule,
+                           activation );
+    }
+
+    protected void modifyInsert(final EntryPoint entryPoint,
+                                final FactHandle factHandle,
+                                final Object object,
+                                final Rule rule,
+                                final Activation activation) {
+        try {
+            this.lock.lock();
+            this.ruleBase.executeQueuedActions();
+
+            final InternalFactHandle handle = (InternalFactHandle) factHandle;
+            final Object originalObject = (handle.isShadowFact()) ? ((ShadowProxy) handle.getObject()).getShadowedObject() : handle.getObject();
+
+            if ( this.maintainTms ) {
+                EqualityKey key = handle.getEqualityKey();
+
+                // now use an existing EqualityKey, if it exists, else create a
+                // new one
+                key = this.tms.get( object );
+                if ( key == null ) {
+                    key = new EqualityKey( handle,
+                                           0 );
+                    this.tms.put( key );
+                } else {
+                    key.addFactHandle( handle );
+                }
+
+                handle.setEqualityKey( key );
+            }
+
+            this.handleFactory.increaseFactHandleRecency( handle );
+
+            if ( activation != null ) {
+                // release resources so that they can be GC'ed
+                activation.getPropagationContext().releaseResources();
+            }
+            // Nowretract any trace of the original fact
+            final PropagationContext propagationContext = new PropagationContextImpl( this.propagationIdCounter++,
+                                                                                      PropagationContext.MODIFICATION,
+                                                                                      rule,
+                                                                                      activation,
+                                                                                      this.agenda.getActiveActivations(),
+                                                                                      this.agenda.getDormantActivations(),
+                                                                                      entryPoint );
+
+            doInsert( handle,
+                      object,
+                      propagationContext );
+
+            this.workingMemoryEventSupport.fireObjectUpdated( propagationContext,
+                                                              factHandle,
+                                                              originalObject,
+                                                              object,
+                                                              this );
+
+            propagationContext.clearRetractedTuples();
+
+            if ( !this.actionQueue.isEmpty() ) {
+                executeQueuedActions();
+            }
+        } finally {
+            this.lock.unlock();
+        }
+    }
+
+    public void update(final FactHandle handle,
+                       final Object object) throws FactException {
+        update( handle,
+                object,
+                null,
+                null );
+    }
+
+    /**
+     * modify is implemented as half way retract / assert due to the truth
+     * maintenance issues.
+     * 
+     * @see WorkingMemory
+     */
+    public void update(final FactHandle factHandle,
+                       final Object object,
+                       final Rule rule,
+                       final Activation activation) throws FactException {
+        this.update( EntryPoint.DEFAULT,
+                     factHandle,
+                     object,
+                     rule,
+                     activation );
+
+    }
+
+    protected void update(final EntryPoint entryPoint,
+                          final FactHandle factHandle,
+                          final Object object,
+                          final Rule rule,
+                          final Activation activation) throws FactException {
+        try {
+            this.lock.lock();
+            this.ruleBase.executeQueuedActions();
+
+            // only needed if we maintain tms, but either way we must get it
+            // before we do the retract
+            int status = -1;
+            if ( this.maintainTms ) {
+                status = ((InternalFactHandle) factHandle).getEqualityKey().getStatus();
+            }
+            final InternalFactHandle handle = (InternalFactHandle) factHandle;
+            final Object originalObject = (handle.isShadowFact()) ? ((ShadowProxy) handle.getObject()).getShadowedObject() : handle.getObject();
+
+            if ( handle.getId() == -1 || object == null ) {
+                // the handle is invalid, most likely already retracted, so
+                // return
+                // and we cannot assert a null object
+                return;
+            }
+
+            if ( activation != null ) {
+                // release resources so that they can be GC'ed
+                activation.getPropagationContext().releaseResources();
+            }
+            // Nowretract any trace of the original fact
+            final PropagationContext propagationContext = new PropagationContextImpl( this.propagationIdCounter++,
+                                                                                      PropagationContext.MODIFICATION,
+                                                                                      rule,
+                                                                                      activation,
+                                                                                      this.agenda.getActiveActivations(),
+                                                                                      this.agenda.getDormantActivations(),
+                                                                                      entryPoint );
+            doRetract( handle,
+                       propagationContext );
+
+            if ( (originalObject != object) || (this.ruleBase.getConfiguration().getAssertBehaviour() != AssertBehaviour.IDENTITY) ) {
+                this.objectStore.removeHandle( handle );
+
+                // set anyway, so that it updates the hashCodes
+                handle.setObject( object );
+                this.objectStore.addHandle( handle, object );
+            }
+
+            if ( this.maintainTms ) {
+
+                // the hashCode and equality has changed, so we must update the
+                // EqualityKey
+                EqualityKey key = handle.getEqualityKey();
+                key.removeFactHandle( handle );
+
+                // If the equality key is now empty, then remove it
+                if ( key.isEmpty() ) {
+                    this.tms.remove( key );
+                }
+
+                // now use an existing EqualityKey, if it exists, else create a
+                // new one
+                key = this.tms.get( object );
+                if ( key == null ) {
+                    key = new EqualityKey( handle,
+                                           status );
+                    this.tms.put( key );
+                } else {
+                    key.addFactHandle( handle );
+                }
+
+                handle.setEqualityKey( key );
+            }
+
+            this.handleFactory.increaseFactHandleRecency( handle );
+
+            doInsert( handle,
+                      object,
+                      propagationContext );
+
+            this.workingMemoryEventSupport.fireObjectUpdated( propagationContext,
+                                                              factHandle,
+                                                              originalObject,
+                                                              object,
+                                                              this );
+
+            propagationContext.clearRetractedTuples();
+
+            if ( !this.actionQueue.isEmpty() ) {
+                executeQueuedActions();
+            }
+        } finally {
+            this.lock.unlock();
+        }
+    }
+
+    public void executeQueuedActions() {
+        while ( !actionQueue.isEmpty() ) {
+            final WorkingMemoryAction action = (WorkingMemoryAction) actionQueue.get( 0 );
+            actionQueue.remove( 0 );
+            action.execute( this );
+        }
+        // for ( final Iterator it = this.actionQueue.iterator(); it.hasNext();
+        // ) {
+        // final WorkingMemoryAction action = (WorkingMemoryAction) it.next();
+        // it.remove();
+        // action.execute( this );
+        // }
+    }
+
+    public void queueWorkingMemoryAction(final WorkingMemoryAction action) {
+        this.actionQueue.add( action );
+    }
+
+    public void removeLogicalDependencies(final Activation activation,
+                                          final PropagationContext context,
+                                          final Rule rule) throws FactException {
+        if ( this.maintainTms ) {
+            this.tms.removeLogicalDependencies( activation,
+                                                context,
+                                                rule );
+        }
+    }
+
+    /**
+     * Retrieve the <code>JoinMemory</code> for a particular
+     * <code>JoinNode</code>.
+     * 
+     * @param node
+     *            The <code>JoinNode</code> key.
+     * 
+     * @return The node's memory.
+     */
+    public Object getNodeMemory(final NodeMemory node) {
+        return this.nodeMemories.getNodeMemory( node );
+    }
+
+    public void clearNodeMemory(final NodeMemory node) {
+        this.nodeMemories.clearNodeMemory( node );
+    }
+
+    public WorkingMemoryEventSupport getWorkingMemoryEventSupport() {
+        return this.workingMemoryEventSupport;
+    }
+
+    public AgendaEventSupport getAgendaEventSupport() {
+        return this.agendaEventSupport;
+    }
+
+    public RuleFlowEventSupport getRuleFlowEventSupport() {
+        return this.workflowEventSupport;
+    }
+
+    /**
+     * Sets the AsyncExceptionHandler to handle exceptions thrown by the Agenda
+     * Scheduler used for duration rules.
+     * 
+     * @param handler
+     */
+    public void setAsyncExceptionHandler(final AsyncExceptionHandler handler) {
+        // this.agenda.setAsyncExceptionHandler( handler );
+    }
+
+    /*
+     * public void dumpMemory() { Iterator it = this.joinMemories.keySet(
+     * ).iterator( ); while ( it.hasNext( ) ) { ((JoinMemory)
+     * this.joinMemories.get( it.next( ) )).dump( ); } }
+     */
+
+    public void propertyChange(final PropertyChangeEvent event) {
+        final Object object = event.getSource();
+
+        try {
+            FactHandle handle = getFactHandle( object );
+            if ( handle == null ) {
+                throw new FactException( "Update error: handle not found for object: " + object + ". Is it in the working memory?" );
+            }
+            update( handle,
+                    object );
+        } catch ( final FactException e ) {
+            throw new RuntimeDroolsException( e.getMessage() );
+        }
+    }
+
+    public long getNextPropagationIdCounter() {
+        return this.propagationIdCounter++;
+    }
+
+    public Lock getLock() {
+        return this.lock;
+    }
+
+    public class RuleFlowDeactivateEvent {
+
+        public void propagate() {
+
+        }
+    }
+
+    public ProcessInstance startProcess(final String processId) {
+        return startProcess(processId, null);
+    }
+    
+    public ProcessInstance startProcess(String processId, Map<String, Object> parameters) {
+        final Process process = ((InternalRuleBase) getRuleBase()).getProcess( processId );
+        if ( process == null ) {
+            throw new IllegalArgumentException( "Unknown process ID: " + processId );
+        }
+        ProcessInstanceFactory factory = processInstanceFactories.get(process.getType());
+        if (factory == null) {
+            throw new IllegalArgumentException( "Could not create process instance for type: " + process.getType() );
+        }
+        ProcessInstance processInstance = factory.createProcessInstance();
+        processInstance.setWorkingMemory( this );
+        processInstance.setProcess( process );
+        processInstance.setId( ++processCounter );
+        processInstances.put( new Long( processInstance.getId() ),
+                              processInstance );
+        if (parameters != null) {
+            for (Map.Entry<String, Object> entry: parameters.entrySet()) {
+                processInstance.setVariable(entry.getKey(), entry.getValue());
+            }
+        }
+        getRuleFlowEventSupport().fireBeforeRuleFlowProcessStarted( processInstance,
+                                                                    this );
+        processInstance.start();
+        getRuleFlowEventSupport().fireAfterRuleFlowProcessStarted( processInstance,
+                                                                   this );
+
+        return processInstance;
+    }
+
+    public Collection getProcessInstances() {
+        return Collections.unmodifiableCollection( processInstances.values() );
+    }
+
+    public ProcessInstance getProcessInstance(long id) {
+        return (ProcessInstance) processInstances.get( new Long( id ) );
+    }
+
+    public void removeProcessInstance(ProcessInstance processInstance) {
+        processInstances.remove( processInstance );
+    }
+    
+    public void registerProcessInstanceFactory(String type, ProcessInstanceFactory processInstanceFactory) {
+        processInstanceFactories.put(type, processInstanceFactory);
+    }
+
+    public WorkItemManager getWorkItemManager() {
+        return workItemManager;
+    }
+
+    public List iterateObjectsToList() {
+        List result = new ArrayList();
+        Iterator iterator = iterateObjects();
+        for ( ; iterator.hasNext(); ) {
+            result.add( iterator.next() );
+        }
+        return result;
+    }
+
+    public Entry[] getActivationParameters(long activationId) {
+        Activation[] activations = getAgenda().getActivations();
+        for ( int i = 0; i < activations.length; i++ ) {
+            if ( activations[i].getActivationNumber() == activationId ) {
+                Map params = getActivationParameters( activations[i] );
+                return (Entry[]) params.entrySet().toArray( new Entry[params.size()] );
+            }
+        }
+        return new Entry[0];
+    }
+
+    /**
+     * Helper method
+     */
+    public Map getActivationParameters(Activation activation) {
+        Map result = new HashMap();
+        Declaration[] declarations = activation.getRule().getDeclarations();
+        for ( int i = 0; i < declarations.length; i++ ) {
+            FactHandle handle = activation.getTuple().get( declarations[i] );
+            if ( handle instanceof InternalFactHandle ) {
+                result.put( declarations[i].getIdentifier(),
+                            declarations[i].getValue( this,
+                                                      ((InternalFactHandle) handle).getObject() ) );
+            }
+        }
+        return result;
+    }
+
+    /**
+     * The time machine tells you what time it is.
+     */
+    public TimeMachine getTimeMachine() {
+        return timeMachine;
+    }
+
+    /**
+     * The time machine defaults to returning the current time when asked.
+     * However, you can use tell it to go back in time.
+     * 
+     * @param timeMachine
+     */
+    public void setTimeMachine(TimeMachine timeMachine) {
+        this.timeMachine = timeMachine;
+    }
+
+    /**
+     * Returns the ObjectTypeConfiguration object for the given object or
+     * creates a new one if none is found in the cache
+     * 
+     * @param object
+     * @return
+     */
+    public ObjectTypeConf getObjectTypeConf(EntryPoint entrypoint,
+                                            Object object) {
+        Map<Object, ObjectTypeConf> map = this.typeConfMap.get( entrypoint );
+        if ( map == null ) {
+            map = new HashMap<Object, ObjectTypeConf>();
+            this.typeConfMap.put( entrypoint,
+                                  map );
+        }
+        ObjectTypeConf objectTypeConf;
+
+        if ( object instanceof Fact ) {
+            String key = ((Fact) object).getFactTemplate().getName();
+            objectTypeConf = map.get( key );
+            if ( objectTypeConf == null ) {
+                objectTypeConf = new FactTemplateTypeConf( entrypoint,
+                                                           ((Fact) object).getFactTemplate(),
+                                                           this.ruleBase );
+                this.addObjectTypeConf( entrypoint,
+                                        key,
+                                        objectTypeConf );
+            }
+            object = key;
+        } else {
+            Class cls = null;
+            if ( object instanceof ShadowProxy ) {
+                cls = ((ShadowProxy) object).getShadowedObject().getClass();
+            } else {
+                cls = object.getClass();
+            }
+
+            objectTypeConf = map.get( cls );
+            if ( objectTypeConf == null ) {
+
+                objectTypeConf = new ClassObjectTypeConf( entrypoint,
+                                                          cls,
+                                                          this.ruleBase );
+                this.addObjectTypeConf( entrypoint,
+                                        cls,
+                                        objectTypeConf );
+            }
+
+        }
+        return objectTypeConf;
+    }
+
+    public Map<Object, ObjectTypeConf> getObjectTypeConfMap(EntryPoint entryPoint) {
+        Map<Object, ObjectTypeConf> map = this.typeConfMap.get( entryPoint );
+        if ( map == null ) {
+            map = Collections.emptyMap();
+        }
+        return map;
+    }
+
+    private void addObjectTypeConf(EntryPoint entryPoint,
+                                   Object key,
+                                   ObjectTypeConf conf) {
+        Map<Object, ObjectTypeConf> map = this.typeConfMap.get( entryPoint );
+        if ( map == null ) {
+            map = new HashMap<Object, ObjectTypeConf>();
+            this.typeConfMap.put( entryPoint,
+                                  map );
+        }
+        map.put( key,
+                 conf );
+    }
+
+    public EntryPointInterface getEntryPoint(String id) {
+        EntryPoint ep = new EntryPoint( id );
+        return new EntryPointInterfaceImpl( ep,
+                                            this );
+    }
+
+    protected static class EntryPointInterfaceImpl
+        implements
+        EntryPointInterface {
+
+        private static final long           serialVersionUID = 2917871170743358801L;
+
+        private final EntryPoint            entryPoint;
+        private final AbstractWorkingMemory wm;
+
+        public EntryPointInterfaceImpl(EntryPoint entryPoint,
+                                       AbstractWorkingMemory wm) {
+            this.entryPoint = entryPoint;
+            this.wm = wm;
+        }
+
+        public FactHandle insert(Object object) throws FactException {
+            return wm.insert( this.entryPoint,
+                              object, /* Not-Dynamic */
+                              false,
+                              false,
+                              null,
+                              null );
+        }
+
+        public FactHandle insert(Object object,
+                                 boolean dynamic) throws FactException {
+            return wm.insert( this.entryPoint,
+                              object, /* Not-Dynamic */
+                              dynamic,
+                              false,
+                              null,
+                              null );
+        }
+
+        public void modifyInsert(FactHandle factHandle,
+                                 Object object) {
+            wm.modifyInsert( this.entryPoint,
+                             factHandle,
+                             object,
+                             null,
+                             null );
+        }
+
+        public void modifyRetract(FactHandle factHandle) {
+            wm.modifyRetract( this.entryPoint,
+                              factHandle,
+                              null,
+                              null );
+        }
+
+        public void retract(FactHandle handle) throws FactException {
+            wm.retract( this.entryPoint,
+                        handle,
+                        true,
+                        true,
+                        null,
+                        null );
+        }
+
+        public void update(FactHandle handle,
+                           Object object) throws FactException {
+            wm.update( this.entryPoint,
+                       handle,
+                       object,
+                       null,
+                       null );
+        }
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ActivationGroupImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ActivationGroupImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ActivationGroupImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,52 @@
+package org.drools.common;
+
+import org.drools.spi.Activation;
+import org.drools.spi.ActivationGroup;
+import org.drools.util.LinkedList;
+
+public class ActivationGroupImpl
+    implements
+    ActivationGroup {
+    private String           name;
+
+    private final LinkedList list;
+
+    public ActivationGroupImpl(final String name) {
+        this.name = name;
+        this.list = new LinkedList();
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public void addActivation(final Activation activation) {
+        final ActivationGroupNode node = new ActivationGroupNode( activation,
+                                                                  this );
+        activation.setActivationGroupNode( node );
+        this.list.add( node );
+    }
+
+    public void removeActivation(final Activation activation) {
+        final ActivationGroupNode node = activation.getActivationGroupNode();
+        this.list.remove( node );
+        activation.setActivationGroupNode( null );
+    }
+
+    public java.util.Iterator iterator() {
+        return this.list.javaUtilIterator();
+    }
+
+    public boolean isEmpty() {
+        return this.list.isEmpty();
+    }
+
+    public int size() {
+        return this.list.size();
+    }
+
+    public void clear() {
+        this.list.clear();
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ActivationGroupNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ActivationGroupNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ActivationGroupNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,28 @@
+package org.drools.common;
+
+import org.drools.spi.Activation;
+import org.drools.spi.ActivationGroup;
+import org.drools.util.AbstractBaseLinkedListNode;
+
+public class ActivationGroupNode extends AbstractBaseLinkedListNode {
+
+    private Activation      activation;
+
+    private ActivationGroup activationGroup;
+
+    public ActivationGroupNode(final Activation activation,
+                               final ActivationGroup activationGroup) {
+        super();
+        this.activation = activation;
+        this.activationGroup = activationGroup;
+    }
+
+    public Activation getActivation() {
+        return this.activation;
+    }
+
+    public ActivationGroup getActivationGroup() {
+        return this.activationGroup;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/AgendaGroupFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/AgendaGroupFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/AgendaGroupFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,7 @@
+package org.drools.common;
+
+import org.drools.spi.AgendaGroup;
+
+public interface AgendaGroupFactory {    
+    AgendaGroup createAgendaGroup(String name, InternalRuleBase ruleBase);
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/AgendaItem.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/AgendaItem.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/AgendaItem.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,261 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.drools.rule.GroupElement;
+import org.drools.rule.Rule;
+import org.drools.spi.Activation;
+import org.drools.spi.AgendaGroup;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
+import org.drools.util.LinkedList;
+import org.drools.util.Queue;
+import org.drools.util.Queueable;
+
+/**
+ * Item entry in the <code>Agenda</code>.
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ */
+public class AgendaItem
+    implements
+    Activation,
+    Queueable,
+    Serializable {
+    // ------------------------------------------------------------
+    // Instance members
+    // ------------------------------------------------------------
+
+    /**
+     * 
+     */
+    private static final long        serialVersionUID = 400L;
+
+    /** The tuple. */
+    private final Tuple              tuple;
+
+    /** The rule. */
+    private final Rule               rule;
+
+    /** The salience */
+    private final int                salience;
+
+    /** Used for sequential mode */
+    private int                      sequenence;
+
+    /** The subrule */
+    private final GroupElement       subrule;
+
+    /** The propagation context */
+    private final PropagationContext context;
+
+    /** The activation number */
+    private final long               activationNumber;
+
+    /** A reference to the PriorityQeue the item is on */
+    private Queue                    queue;
+
+    private int                      index;
+
+    private LinkedList               justified;
+
+    private boolean                  activated;
+
+    private InternalAgendaGroup      agendaGroup;
+
+    private ActivationGroupNode      activationGroupNode;
+
+    private RuleFlowGroupNode        ruleFlowGroupNode;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    /**
+     * Construct.
+     * 
+     * @param tuple
+     *            The tuple.
+     * @param rule
+     *            The rule.
+     */
+    public AgendaItem(final long activationNumber,
+                      final Tuple tuple,
+                      final int salience,
+                      final PropagationContext context,
+                      final Rule rule,
+                      final GroupElement subrule) {
+        this.tuple = tuple;
+        this.context = context;
+        this.rule = rule;
+        this.salience = salience;
+        this.subrule = subrule;
+        this.activationNumber = activationNumber;
+    }
+
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+    public PropagationContext getPropagationContext() {
+        return this.context;
+    }
+
+    /**
+     * Retrieve the rule.
+     * 
+     * @return The rule.
+     */
+    public Rule getRule() {
+        return this.rule;
+    }
+
+    /**
+     * Retrieve the tuple.
+     * 
+     * @return The tuple.
+     */
+    public Tuple getTuple() {
+        return this.tuple;
+    }
+
+    public int getSalience() {
+        return this.salience;
+    }
+
+    public int getSequenence() {
+        return sequenence;
+    }
+
+    public void setSequenence(int sequenence) {
+        this.sequenence = sequenence;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.drools.spi.Activation#getActivationNumber()
+     */
+    public long getActivationNumber() {
+        return this.activationNumber;
+    }
+
+    public void addLogicalDependency(final LogicalDependency node) {
+        if ( this.justified == null ) {
+            this.justified = new LinkedList();
+        }
+
+        this.justified.add( node );
+    }
+
+    public LinkedList getLogicalDependencies() {
+        return this.justified;
+    }
+
+    public void setLogicalDependencies(LinkedList justified) {
+        this.justified = justified;
+    }
+
+    public boolean isActivated() {
+        return this.activated;
+    }
+
+    public void setActivated(final boolean activated) {
+        this.activated = activated;
+    }
+
+    public String toString() {
+        return "[Activation rule=" + this.rule.getName() + ", tuple=" + this.tuple + "]";
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    public boolean equals(final Object object) {
+        if ( object == this ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof AgendaItem) ) {
+            return false;
+        }
+
+        final AgendaItem otherItem = (AgendaItem) object;
+
+        return (this.rule.equals( otherItem.getRule() ) && this.tuple.equals( otherItem.getTuple() ));
+    }
+
+    /**
+     * Return the hashCode of the
+     * <code>TupleKey<code> as the hashCode of the AgendaItem
+     * @return
+     */
+    public int hashCode() {
+        return this.tuple.hashCode();
+    }
+
+    public void enqueued(final Queue queue,
+                         final int index) {
+        this.queue = queue;
+        this.index = index;
+    }
+
+    public void dequeue() {
+        if ( this.queue != null ) {
+            // will only be null if the AgendaGroup is locked when the activation add was attempted
+            this.queue.dequeue( this.index );
+            this.queue = null;
+        }
+        this.activated = false;
+    }
+
+    public void remove() {
+        dequeue();
+    }
+
+    public ActivationGroupNode getActivationGroupNode() {
+        return this.activationGroupNode;
+    }
+
+    public void setActivationGroupNode(final ActivationGroupNode activationNode) {
+        this.activationGroupNode = activationNode;
+    }
+
+    public AgendaGroup getAgendaGroup() {
+        return this.agendaGroup;
+    }
+
+    public void setAgendaGroup(final InternalAgendaGroup agendaGroup) {
+        this.agendaGroup = agendaGroup;
+    }
+
+    public RuleFlowGroupNode getRuleFlowGroupNode() {
+        return this.ruleFlowGroupNode;
+    }
+
+    public void setRuleFlowGroupNode(final RuleFlowGroupNode ruleFlowGroupNode) {
+        this.ruleFlowGroupNode = ruleFlowGroupNode;
+    }
+
+    public GroupElement getSubRule() {
+        return this.subrule;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ArrayAgendaGroup.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ArrayAgendaGroup.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ArrayAgendaGroup.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,201 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.conflict.DepthConflictResolver;
+import org.drools.spi.Activation;
+import org.drools.spi.AgendaGroup;
+import org.drools.spi.ConflictResolver;
+import org.drools.util.BinaryHeapQueue;
+import org.drools.util.Iterator;
+import org.drools.util.LinkedList;
+import org.drools.util.LinkedListEntry;
+import org.drools.util.PrimitiveLongMap;
+import org.drools.util.Queueable;
+import org.drools.util.LinkedList.LinkedListIterator;
+
+/**
+ * <code>AgendaGroup</code> implementation that uses a <code>PriorityQueue</code> to prioritise the evaluation of added
+ * <code>ActivationQueue</code>s. The <code>AgendaGroup</code> also maintains a <code>Map</code> of <code>ActivationQueues</code> 
+ * for requested salience values.
+ * 
+ * @see PriorityQueue
+ * @see ActivationQueue
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ *
+ */
+public class ArrayAgendaGroup
+    implements
+    InternalAgendaGroup {
+
+    private static final long serialVersionUID = 400L;
+
+    private final String      name;
+
+    /** Items in the agenda. */
+    private LinkedList[]      array;
+
+    private boolean           active;
+
+    private int               size;
+
+    private int               index;
+
+    private int               lastIndex;
+
+    /**
+     * Construct an <code>AgendaGroup</code> with the given name.
+     * 
+     * @param name
+     *      The <AgendaGroup> name.
+     */
+
+    public ArrayAgendaGroup(final String name,
+                            final InternalRuleBase ruleBase) {
+        this.name = name;
+        Integer integer = (Integer) ruleBase.getAgendaGroupRuleTotals().get( name );
+           
+        if ( integer == null ) {
+            this.array = new LinkedList[0];
+        } else {
+            this.array = new LinkedList[integer.intValue()];    
+        }
+
+        this.index = this.array.length-1; 
+        this.lastIndex = 0;        
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.spi.AgendaGroup#getName()
+     */
+    public String getName() {
+        return this.name;
+    }
+
+    public void clear() {
+        this.array = new LinkedList[this.array.length];
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.spi.AgendaGroup#size()
+     */
+    public int size() {
+        return this.size;
+    }
+
+    public void add(final Activation activation) {
+        AgendaItem item = (AgendaItem) activation;
+        this.size++;
+        int seq = item.getSequenence();
+        
+        if ( seq < this.index ) {
+            this.index = seq;
+        }
+        
+        if ( seq > this.lastIndex ) {
+            this.lastIndex = seq;
+        }
+        
+        LinkedList list = this.array[seq];
+        if ( list == null ) {
+            list = new LinkedList();
+            this.array[item.getSequenence()] = list;
+        }
+        
+        list.add( new LinkedListEntry( activation ) );
+    }
+
+    public Activation getNext() {
+        Activation activation = null;
+        while ( this.index <= lastIndex ) {
+            LinkedList list = this.array[this.index];            
+            if ( list != null ) {
+                activation = (Activation) ((LinkedListEntry)list.removeFirst()).getObject();
+                if ( list.isEmpty()) {
+                    this.array[this.index++] = null;
+                }
+                this.size--;
+                break;
+            }
+            this.index++;
+        }
+        return (Activation) activation;
+    }
+
+    public boolean isActive() {
+        return this.active;
+    }
+
+    public void setActive(final boolean activate) {
+        this.active = activate;
+    }
+
+    /**
+     * Iterates a PriorityQueue removing empty entries until it finds a populated entry and return true,
+     * otherwise it returns false;
+     * 
+     * @param priorityQueue
+     * @return
+     */
+    public boolean isEmpty() {
+        return this.size == 0;
+    }
+
+    public Activation[] getActivations() {
+        Activation[] activations = new Activation[this.size];
+        int j = 0;
+        for ( int i = 0; i < this.array.length; i++ ) {;
+            LinkedList list = this.array[i];
+            if ( list != null ) {
+                Iterator it = list.iterator();
+                Activation activation = ( Activation ) ((LinkedListEntry)it.next()).getObject();
+                while ( activation != null) {
+                    activations[j++] = activation;
+                    activation = ( Activation ) it.next();
+                }
+            }
+            
+        }
+        return activations;
+    }
+
+    public Activation[] getQueue() {
+        return getActivations();
+    }
+
+    public String toString() {
+        return "AgendaGroup '" + this.name + "'";
+    }
+
+    public boolean equal(final Object object) {
+        if ( (object == null) || !(object instanceof ArrayAgendaGroup) ) {
+            return false;
+        }
+
+        if ( ((ArrayAgendaGroup) object).name.equals( this.name ) ) {
+            return true;
+        }
+
+        return false;
+    }
+
+    public int hashCode() {
+        return this.name.hashCode();
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ArrayAgendaGroupFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ArrayAgendaGroupFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ArrayAgendaGroupFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,16 @@
+package org.drools.common;
+
+import org.drools.spi.AgendaGroup;
+
+public class ArrayAgendaGroupFactory implements AgendaGroupFactory {
+    private static final AgendaGroupFactory INSTANCE = new ArrayAgendaGroupFactory();
+    
+    public static AgendaGroupFactory getInstance() {
+        return INSTANCE;
+    }    
+    
+    public AgendaGroup createAgendaGroup(String name, InternalRuleBase ruleBase) {
+        return new ArrayAgendaGroup( name,
+                                     ruleBase );        
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/BaseNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/BaseNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/BaseNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,138 @@
+package org.drools.common;
+
+import org.drools.reteoo.ReteooBuilder;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * The base class for all Rete nodes.
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ *
+ */
+public abstract class BaseNode
+    implements
+    NetworkNode {
+    protected final int id;
+
+    protected int       sharedCount = 0;
+
+    /**
+     * All nodes have a unique id, set in the constructor.
+     * 
+     * @param id
+     *      The unique id
+     */
+    public BaseNode(final int id) {
+        super();
+        this.id = id;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.spi.ReteooNode#getId()
+     */
+    public int getId() {
+        return this.id;
+    }
+
+    /**
+     * Attaches the node into the network. Usually to the parent <code>ObjectSource</code> or <code>TupleSource</code>
+     */
+    public abstract void attach();
+
+    public abstract void attach(InternalWorkingMemory[] workingMemories);
+
+    /**
+     * Removes the node from teh network. Usually from the parent <code>ObjectSource</code> or <code>TupleSource</code>
+     * @param builder TODO
+     *
+     */
+    public abstract void remove(ReteooBuilder builder,
+                                BaseNode node,
+                                InternalWorkingMemory[] workingMemories);
+
+    //    /**
+    //     * When nodes are added to the network that already has data. that existing data must be repropagated to the new node.
+    //     * This new propagation may result in one or more assertions, so a PropagationContext and the workingMemory for the facts
+    //     * must be provided.
+    //     * 
+    //     * @param workingMemory
+    //     *      The WorkingMemory
+    //     * @param context
+    //     *      The PropagationContext
+    //     *      
+    //     */
+    //    public abstract void updateNewNode(InternalWorkingMemory workingMemory,
+    //                                       PropagationContext context);    
+
+    /**
+     * Each time a node is shared a counter is increased.
+     *
+     */
+    public void addShare() {
+        ++this.sharedCount;
+    }
+
+    /**
+     * Each time a node is unshared a counter is decreased.
+     * @param builder TODO
+     *
+     */
+    public void removeShare(ReteooBuilder builder) {
+        --this.sharedCount;
+        if( !this.isInUse() ) {
+            builder.getIdGenerator().releaseId( this.id );
+        }
+    }
+
+    /**
+     * Indicates whether the node is shared.
+     * @return
+     */
+    public boolean isShared() {
+        return this.sharedCount > 0;
+    }
+
+    /**
+     * Returns true in case the current node is in use (is referenced by any other node)
+     * @return
+     */
+    public boolean isInUse() {
+        return this.sharedCount >= 0;
+    }
+
+    /**
+     * Returns the number of times the node is shared
+     * @return
+     *      int value indicating the share count.
+     */
+    public int getSharedCount() {
+        return this.sharedCount;
+    }
+
+    /** 
+     * The hashCode return is simply the unique id of the node. It is expected that base classes will also implement equals(Object object). 
+     */
+    public int hashCode() {
+        return this.id;
+    }
+
+    public String toString() {
+        return "[" + this.getClass().getName() + "(" + this.id + ")]";
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/BetaConstraints.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/BetaConstraints.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/BetaConstraints.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,37 @@
+package org.drools.common;
+
+import java.io.Serializable;
+
+import org.drools.RuleBaseConfiguration;
+import org.drools.reteoo.BetaMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.util.LinkedList;
+
+public interface BetaConstraints
+    extends
+    Serializable {
+
+    public void updateFromTuple(InternalWorkingMemory workingMemory,
+                                ReteTuple tuple);
+
+    public void updateFromFactHandle(InternalWorkingMemory workingMemory,
+                                     InternalFactHandle handle);
+
+    public boolean isAllowedCachedLeft(InternalFactHandle handle);
+
+    public boolean isAllowedCachedRight(ReteTuple tuple);
+
+    public LinkedList getConstraints();
+
+    public boolean isIndexed();
+    
+    public int getIndexCount();
+
+    public boolean isEmpty();
+
+    public BetaMemory createBetaMemory(final RuleBaseConfiguration config);
+    
+    public void resetTuple();
+    
+    public void resetFactHandle();    
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/BinaryHeapQueueAgendaGroup.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/BinaryHeapQueueAgendaGroup.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/BinaryHeapQueueAgendaGroup.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,136 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.conflict.DepthConflictResolver;
+import org.drools.spi.Activation;
+import org.drools.spi.AgendaGroup;
+import org.drools.spi.ConflictResolver;
+import org.drools.util.BinaryHeapQueue;
+import org.drools.util.Queueable;
+
+/**
+ * <code>AgendaGroup</code> implementation that uses a <code>PriorityQueue</code> to prioritise the evaluation of added
+ * <code>ActivationQueue</code>s. The <code>AgendaGroup</code> also maintains a <code>Map</code> of <code>ActivationQueues</code> 
+ * for requested salience values.
+ * 
+ * @see PriorityQueue
+ * @see ActivationQueue
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ *
+ */
+public class BinaryHeapQueueAgendaGroup
+    implements
+    InternalAgendaGroup {
+
+    private static final long     serialVersionUID = 400L;
+
+    private final String          name;
+
+    /** Items in the agenda. */
+    private final BinaryHeapQueue queue;
+
+    private boolean               active;
+
+    /**
+     * Construct an <code>AgendaGroup</code> with the given name.
+     * 
+     * @param name
+     *      The <AgendaGroup> name.
+     */
+    
+    
+    public BinaryHeapQueueAgendaGroup(final String name, final InternalRuleBase ruleBase) {
+        this.name = name;
+        this.queue = new BinaryHeapQueue( ruleBase.getConfiguration().getConflictResolver() );
+    }    
+
+    /* (non-Javadoc)
+     * @see org.drools.spi.AgendaGroup#getName()
+     */
+    public String getName() {
+        return this.name;
+    }
+
+    public void clear() {
+        this.queue.clear();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.spi.AgendaGroup#size()
+     */
+    public int size() {
+        return this.queue.size();
+    }
+
+    public void add(final Activation activation) {
+        this.queue.enqueue( (Queueable) activation );
+    }
+
+    public Activation getNext() {
+        return (Activation) this.queue.dequeue();
+    }
+
+    public boolean isActive() {
+        return this.active;
+    }
+
+    public void setActive(final boolean activate) {
+        this.active = activate;
+    }
+
+    /**
+     * Iterates a PriorityQueue removing empty entries until it finds a populated entry and return true,
+     * otherwise it returns false;
+     * 
+     * @param priorityQueue
+     * @return
+     */
+    public boolean isEmpty() {
+        return this.queue.isEmpty();
+    }
+
+    public Activation[] getActivations() {
+        return (Activation[]) this.queue.toArray( new AgendaItem[this.queue.size()] );
+    }
+
+    public Activation[] getQueue() {
+        return this.queue.getQueueable();
+    }
+
+    public String toString() {
+        return "AgendaGroup '" + this.name + "'";
+    }
+
+    public boolean equal(final Object object) {
+        if ( (object == null) || !(object instanceof BinaryHeapQueueAgendaGroup) ) {
+            return false;
+        }
+
+        if ( ((BinaryHeapQueueAgendaGroup) object).name.equals( this.name ) ) {
+            return true;
+        }
+
+        return false;
+    }
+
+    public int hashCode() {
+        return this.name.hashCode();
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ConcurrentNodeMemories.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ConcurrentNodeMemories.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ConcurrentNodeMemories.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2008 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.
+ *
+ * Created on Jan 15, 2008
+ */
+
+package org.drools.common;
+
+import java.util.concurrent.atomic.AtomicReferenceArray;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * A concurrent implementation for the node memories interface
+ * 
+ * @author etirelli
+ */
+public class ConcurrentNodeMemories
+    implements
+    NodeMemories {
+
+    private static final long serialVersionUID = -2032997426288974117L;
+    
+    private AtomicReferenceArray<Object> memories;
+    private Lock                         lock;
+    private transient InternalRuleBase   rulebase;
+
+    public ConcurrentNodeMemories(InternalRuleBase rulebase) {
+        this.rulebase = rulebase;
+        this.memories = new AtomicReferenceArray<Object>( this.rulebase.getNodeCount() );
+        this.lock = new ReentrantLock();
+    }
+
+    /**
+     * @inheritDoc
+     *
+     * @see org.drools.common.NodeMemories#clearNodeMemory(org.drools.common.NodeMemory)
+     */
+    public void clearNodeMemory(NodeMemory node) {
+        this.memories.set( node.getId(), null );
+    }
+
+    /**
+     * @inheritDoc
+     *
+     * @see org.drools.common.NodeMemories#getNodeMemory(org.drools.common.NodeMemory)
+     */
+    public Object getNodeMemory(NodeMemory node) {
+        if ( node.getId() >= this.memories.length() ) {
+            resize( node );
+        }
+        Object memory = this.memories.get( node.getId() );
+
+        if ( memory == null ) {
+            memory = node.createMemory( this.rulebase.getConfiguration() );
+
+            if( !this.memories.compareAndSet( node.getId(), null, memory ) ) {
+                memory = this.memories.get( node.getId() );
+            }
+        }
+
+        return memory;
+    }
+
+    /**
+     * @param node
+     */
+    private void resize(NodeMemory node) {
+        this.lock.lock();
+        try {
+            if( node.getId() >= this.memories.length() ) {
+                int size = Math.max( this.rulebase.getNodeCount(),
+                                     node.getId() + 1 );
+                AtomicReferenceArray<Object> newMem = new AtomicReferenceArray<Object>( size );
+                for( int i = 0; i < this.memories.length(); i++ ) {
+                    newMem.set( i, this.memories.get( i ) );
+                }
+                this.memories = newMem;
+            }
+        } finally {
+            this.lock.unlock();
+        }
+    }
+
+    public void setRuleBaseReference(InternalRuleBase ruleBase) {
+        this.rulebase = ruleBase;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/DefaultAgenda.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/DefaultAgenda.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/DefaultAgenda.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,590 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.WorkingMemory;
+import org.drools.base.DefaultKnowledgeHelper;
+import org.drools.base.SequentialKnowledgeHelper;
+import org.drools.common.RuleFlowGroupImpl.DeactivateCallback;
+import org.drools.spi.Activation;
+import org.drools.spi.ActivationGroup;
+import org.drools.spi.AgendaFilter;
+import org.drools.spi.AgendaGroup;
+import org.drools.spi.ConflictResolver;
+import org.drools.spi.ConsequenceException;
+import org.drools.spi.ConsequenceExceptionHandler;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.RuleFlowGroup;
+import org.drools.util.LinkedListNode;
+import org.drools.util.Queueable;
+
+/**
+ * Rule-firing Agenda.
+ * 
+ * <p>
+ * Since many rules may be matched by a single assertObject(...) all scheduled
+ * actions are placed into the <code>Agenda</code>.
+ * </p>
+ * 
+ * <p>
+ * While processing a scheduled action, it may update or retract objects in
+ * other scheduled actions, which must then be removed from the agenda.
+ * Non-invalidated actions are left on the agenda, and are executed in turn.
+ * </p>
+ * 
+ * @author <a href="mailto:bob at eng.werken.com">bob mcwhirter </a>
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris </a>
+ */
+public class DefaultAgenda
+    implements
+    Serializable,
+    InternalAgenda {
+    // ------------------------------------------------------------
+    // Instance members
+    // ------------------------------------------------------------
+
+    /**
+     * 
+     */
+    private static final long           serialVersionUID = 400L;
+
+    /** Working memory of this Agenda. */
+    private final InternalWorkingMemory workingMemory;
+
+    private org.drools.util.LinkedList  scheduledActivations;
+
+    /** Items time-delayed. */
+
+    private final Map                   agendaGroups;
+
+    private final Map                   activationGroups;
+
+    private final Map                   ruleFlowGroups;
+
+    private final LinkedList            focusStack;
+
+    private AgendaGroup                 currentModule;
+
+    private final AgendaGroup           main;
+
+    private AgendaGroupFactory          agendaGroupFactory;
+
+    private KnowledgeHelper             knowledgeHelper;
+
+    public int                          activeActivations;
+
+    public int                          dormantActivations;
+    
+    private ConsequenceExceptionHandler consequenceExceptionHandler;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    /**
+     * Construct.
+     * 
+     * @param workingMemory
+     *            The <code>WorkingMemory</code> of this agenda.
+     * @param conflictResolver
+     *            The conflict resolver.
+     */
+    public DefaultAgenda(final InternalWorkingMemory workingMemory) {
+        this.workingMemory = workingMemory;
+        if ( ((InternalRuleBase) this.workingMemory.getRuleBase()).getConfiguration().isSequential() ) {
+            this.knowledgeHelper = new SequentialKnowledgeHelper( this.workingMemory );
+        } else {
+            this.knowledgeHelper = new DefaultKnowledgeHelper( this.workingMemory );
+        }
+        this.agendaGroups = new HashMap();
+        this.activationGroups = new HashMap();
+        this.ruleFlowGroups = new HashMap();
+        this.focusStack = new LinkedList();
+
+        this.agendaGroupFactory = ((InternalRuleBase) this.workingMemory.getRuleBase()).getConfiguration().getAgendaGroupFactory();
+
+        // MAIN should always be the first AgendaGroup and can never be removed
+        this.main = agendaGroupFactory.createAgendaGroup( AgendaGroup.MAIN,
+                                                          ((InternalRuleBase) this.workingMemory.getRuleBase()) );
+
+        this.agendaGroups.put( AgendaGroup.MAIN,
+                               this.main );
+
+        this.focusStack.add( this.main );
+        
+        this.consequenceExceptionHandler = ((InternalRuleBase) workingMemory.getRuleBase()).getConfiguration().getConsequenceExceptionHandler();
+
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.AgendaI#getWorkingMemory()
+     */
+    public WorkingMemory getWorkingMemory() {
+        return this.workingMemory;
+    }
+
+    /**
+     * Schedule an agenda item for delayed firing.
+     * 
+     * @param item
+     *            The item to schedule.
+     */
+    public void scheduleItem(final ScheduledAgendaItem item) {
+        Scheduler.getInstance().scheduleAgendaItem( item );
+
+        if ( this.scheduledActivations == null ) {
+            this.scheduledActivations = new org.drools.util.LinkedList();
+        }
+
+        this.scheduledActivations.add( item );
+    }
+
+    public void removeScheduleItem(final ScheduledAgendaItem item) {
+        this.scheduledActivations.remove( item );
+        item.cancel();
+    }
+
+    public void addAgendaGroup(final AgendaGroup agendaGroup) {
+        this.agendaGroups.put( agendaGroup.getName(),
+                               agendaGroup );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.AgendaI#setFocus(org.drools.spi.AgendaGroup)
+     */
+    public boolean setFocus(final AgendaGroup agendaGroup) {
+        // Set the focus to the agendaGroup if it doesn't already have the focus
+        if ( this.focusStack.getLast() != agendaGroup ) {
+            ((InternalAgendaGroup) this.focusStack.getLast()).setActive( false );
+            this.focusStack.add( agendaGroup );
+            ((InternalAgendaGroup) agendaGroup).setActive( true );
+            final EventSupport eventsupport = (EventSupport) this.workingMemory;
+            eventsupport.getAgendaEventSupport().fireAgendaGroupPushed( agendaGroup, this.workingMemory );
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.AgendaI#setFocus(java.lang.String)
+     */
+    public void setFocus(final String name) {
+        AgendaGroup agendaGroup = getAgendaGroup( name );
+        setFocus( agendaGroup );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.AgendaI#getFocus()
+     */
+    public AgendaGroup getFocus() {
+        return (AgendaGroup) this.focusStack.getLast();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.AgendaI#getNextFocus()
+     */
+    public AgendaGroup getNextFocus() {
+        InternalAgendaGroup agendaGroup = null;
+        // Iterate untill we find a populate AgendaModule or we reach the MAIN, default, AgendaGroup
+        while ( true ) {
+            agendaGroup = (InternalAgendaGroup) this.focusStack.getLast();
+
+            final boolean empty = agendaGroup.isEmpty();
+
+            // No populated queus found so pop the focusStack and repeat            
+            if ( empty && (this.focusStack.size() > 1) ) {
+                agendaGroup.setActive( false );
+                this.focusStack.removeLast();
+                final EventSupport eventsupport = (EventSupport) this.workingMemory;
+                eventsupport.getAgendaEventSupport().fireAgendaGroupPopped( agendaGroup, this.workingMemory );
+            } else {
+                agendaGroup = (empty) ? null : agendaGroup;
+                break;
+            }
+        }
+
+        if ( agendaGroup != null ) {
+            agendaGroup.setActive( true );
+        }
+        return agendaGroup;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.AgendaI#setCurrentAgendaGroup(org.drools.spi.AgendaGroup)
+     */
+    public void setCurrentAgendaGroup(final AgendaGroup agendaGroup) {
+        this.currentModule = agendaGroup;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.AgendaI#getCurrentAgendaGroup()
+     */
+    public AgendaGroup getCurrentAgendaGroup() {
+        return this.currentModule;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.AgendaI#getAgendaGroup(java.lang.String)
+     */
+    public AgendaGroup getAgendaGroup(final String name) {
+        AgendaGroup agendaGroup = (AgendaGroup) this.agendaGroups.get( name );
+        if ( agendaGroup == null ) {
+            // The AgendaGroup is defined but not yet added to the
+            // Agenda, so create the AgendaGroup and add to the Agenda.
+            agendaGroup = agendaGroupFactory.createAgendaGroup( name,
+                                                                ((InternalRuleBase) this.workingMemory.getRuleBase()) );
+            addAgendaGroup( agendaGroup );
+        }
+        return agendaGroup;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.AgendaI#getAgendaGroups()
+     */
+    public AgendaGroup[] getAgendaGroups() {
+        return (AgendaGroup[]) this.agendaGroups.values().toArray( new AgendaGroup[this.agendaGroups.size()] );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.AgendaI#getStack()
+     */
+    public AgendaGroup[] getStack() {
+        return (AgendaGroup[]) this.focusStack.toArray( new AgendaGroup[this.focusStack.size()] );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.AgendaI#getActivationGroup(java.lang.String)
+     */
+    public ActivationGroup getActivationGroup(final String name) {
+        ActivationGroupImpl activationGroup = (ActivationGroupImpl) this.activationGroups.get( name );
+        if ( activationGroup == null ) {
+            activationGroup = new ActivationGroupImpl( name );
+            this.activationGroups.put( name,
+                                       activationGroup );
+        }
+        return activationGroup;
+    }
+
+    public RuleFlowGroup getRuleFlowGroup(final String name) {
+        RuleFlowGroup ruleFlowGroup = (RuleFlowGroup) this.ruleFlowGroups.get( name );
+        if ( ruleFlowGroup == null ) {
+            ruleFlowGroup = new RuleFlowGroupImpl( name );
+            ((InternalRuleFlowGroup) ruleFlowGroup).setWorkingMemory( (InternalWorkingMemory) getWorkingMemory() );
+            this.ruleFlowGroups.put( name,
+                                     ruleFlowGroup );
+        }
+        return ruleFlowGroup;
+    }
+
+    public void activateRuleFlowGroup(final String name) {
+        ((InternalRuleFlowGroup) getRuleFlowGroup( name )).setActive( true );
+    }
+
+    public void deactivateRuleFlowGroup(final String name) {
+        ((InternalRuleFlowGroup) getRuleFlowGroup( name )).setActive( false );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.AgendaI#focusStackSize()
+     */
+    public int focusStackSize() {
+        int size = 0;
+        for ( final java.util.Iterator iterator = this.focusStack.iterator(); iterator.hasNext(); ) {
+            final AgendaGroup group = (AgendaGroup) iterator.next();
+            size += group.size();
+        }
+        return size;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.AgendaI#agendaSize()
+     */
+    public int agendaSize() {
+        int size = 0;
+        for ( final java.util.Iterator iterator = this.agendaGroups.values().iterator(); iterator.hasNext(); ) {
+            final AgendaGroup group = (AgendaGroup) iterator.next();
+            size += group.size();
+        }
+        return size;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.AgendaI#getActivations()
+     */
+    public Activation[] getActivations() {
+        final List list = new ArrayList();
+        for ( final java.util.Iterator it = this.agendaGroups.values().iterator(); it.hasNext(); ) {
+            final AgendaGroup group = (AgendaGroup) it.next();
+            list.addAll( Arrays.asList( group.getActivations() ) );
+        }
+        return (Activation[]) list.toArray( new Activation[list.size()] );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.AgendaI#getScheduledActivations()
+     */
+    public Activation[] getScheduledActivations() {
+        final List list = new ArrayList( this.scheduledActivations.size() );
+        for ( LinkedListNode node = this.scheduledActivations.getFirst(); node != null; node = node.getNext() ) {
+            list.add( node );
+        }
+        return (Activation[]) list.toArray( new Activation[list.size()] );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.AgendaI#clearAgenda()
+     */
+    public void clearAgenda() {
+        // Cancel all items and fire a Cancelled event for each Activation
+        for ( final java.util.Iterator agendaGroupIterator = this.agendaGroups.values().iterator(); agendaGroupIterator.hasNext(); ) {
+            final AgendaGroup group = (AgendaGroup) agendaGroupIterator.next();
+            clearAgendaGroup( group );
+        }
+
+        final EventSupport eventsupport = (EventSupport) this.workingMemory;
+        if ( this.scheduledActivations != null && !this.scheduledActivations.isEmpty() ) {
+            for ( ScheduledAgendaItem item = (ScheduledAgendaItem) this.scheduledActivations.removeFirst(); item != null; item = (ScheduledAgendaItem) this.scheduledActivations.removeFirst() ) {
+                item.cancel();                
+                eventsupport.getAgendaEventSupport().fireActivationCancelled( item,
+                                                                              this.workingMemory );
+            }
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.AgendaI#clearAgendaGroup(java.lang.String)
+     */
+    public void clearAgendaGroup(final String name) {
+        final AgendaGroup agendaGroup = (AgendaGroup) this.agendaGroups.get( name );
+        if ( agendaGroup != null ) {
+            clearAgendaGroup( agendaGroup );
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.AgendaI#clearAgendaGroup(org.drools.common.AgendaGroupImpl)
+     */
+    public void clearAgendaGroup(final AgendaGroup agendaGroup) {
+        final EventSupport eventsupport = (EventSupport) this.workingMemory;
+
+        final Activation[] queueable = ((InternalAgendaGroup) agendaGroup).getQueue();
+        for ( int i = 0, length = queueable.length; i < length; i++ ) {
+            final AgendaItem item = (AgendaItem) queueable[i];
+            if ( item == null ) {
+                continue;
+            }
+
+            // this must be set false before removal from the activationGroup. Otherwise the activationGroup will also try to cancel the Actvation
+            item.setActivated( false );
+
+            if ( item.getActivationGroupNode() != null ) {
+                item.getActivationGroupNode().getActivationGroup().removeActivation( item );
+            }
+
+            if ( item.getRuleFlowGroupNode() != null ) {
+                final InternalRuleFlowGroup ruleFlowGroup = item.getRuleFlowGroupNode().getRuleFlowGroup();
+                ruleFlowGroup.removeActivation( item );
+            }
+
+            eventsupport.getAgendaEventSupport().fireActivationCancelled( item,
+                                                                          this.workingMemory );
+        }
+        ((InternalAgendaGroup) agendaGroup).clear();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.AgendaI#clearActivationGroup(java.lang.String)
+     */
+    public void clearActivationGroup(final String name) {
+        final ActivationGroup activationGroup = (ActivationGroup) this.activationGroups.get( name );
+        if ( activationGroup != null ) {
+            clearActivationGroup( activationGroup );
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.AgendaI#clearActivationGroup(org.drools.spi.ActivationGroup)
+     */
+    public void clearActivationGroup(final ActivationGroup activationGroup) {
+        final EventSupport eventsupport = (EventSupport) this.workingMemory;
+
+        for ( final Iterator it = activationGroup.iterator(); it.hasNext(); ) {
+            final ActivationGroupNode node = (ActivationGroupNode) it.next();
+            final Activation activation = node.getActivation();
+            activation.setActivationGroupNode( null );
+
+            if ( activation.isActivated() ) {
+                activation.setActivated( false );
+                activation.remove();
+
+                if ( activation.getRuleFlowGroupNode() != null ) {
+                    final InternalRuleFlowGroup ruleFlowGroup = activation.getRuleFlowGroupNode().getRuleFlowGroup();
+                    ruleFlowGroup.removeActivation( activation );
+                }
+
+                eventsupport.getAgendaEventSupport().fireActivationCancelled( activation,
+                                                                              this.workingMemory );
+            }
+        }
+        activationGroup.clear();
+    }
+    
+    public void clearRuleFlowGroup(final String name) {
+        final RuleFlowGroup ruleFlowGrlup = (RuleFlowGroup) this.ruleFlowGroups.get( name );
+        if ( ruleFlowGrlup != null ) {
+            clearRuleFlowGroup( ruleFlowGrlup );
+        }
+    }    
+    
+    public void clearRuleFlowGroup(final RuleFlowGroup ruleFlowGroup) {
+        final EventSupport eventsupport = (EventSupport) this.workingMemory;
+
+        
+        for ( Iterator it = ruleFlowGroup.iterator(); it.hasNext(); ) {
+            RuleFlowGroupNode node = ( RuleFlowGroupNode ) it.next();
+            AgendaItem item = ( AgendaItem ) node.getActivation();            
+            if ( item != null ) {
+                item.setActivated( false );
+                item.remove();
+                
+                if ( item.getActivationGroupNode() != null ) {
+                    item.getActivationGroupNode().getActivationGroup().removeActivation( item );
+                }                
+            }
+            
+        
+            
+            eventsupport.getAgendaEventSupport().fireActivationCancelled( item,
+                                                                          this.workingMemory );                        
+        }
+        
+        ((InternalRuleFlowGroup) ruleFlowGroup).clear();       
+        
+        if ( ruleFlowGroup.isActive() && ruleFlowGroup.isAutoDeactivate() ) {
+                // deactivate callback
+                WorkingMemoryAction action = new DeactivateCallback( (InternalRuleFlowGroup) ruleFlowGroup );
+                this.workingMemory.queueWorkingMemoryAction( action );
+        }        
+    }    
+
+    /**
+     * Fire the next scheduled <code>Agenda</code> item.
+     * 
+     * @throws ConsequenceException
+     *             If an error occurs while firing an agenda item.
+     */
+    public boolean fireNextItem(final AgendaFilter filter) throws ConsequenceException {
+        final InternalAgendaGroup group = (InternalAgendaGroup) getNextFocus();
+
+        // return if there are no Activations to fire
+        if ( group == null ) {
+            return false;
+        }
+
+        final AgendaItem item = (AgendaItem) group.getNext();
+        if ( item == null ) {
+            return false;
+        }
+
+        if ( filter == null || filter.accept( item ) ) {
+            fireActivation( item );
+        }
+
+        return true;
+    }
+
+    /**
+     * Fire this item.
+     * 
+     * @param workingMemory
+     *            The working memory context.
+     * 
+     * @throws ConsequenceException
+     *             If an error occurs while attempting to fire the consequence.
+     */
+    public synchronized void fireActivation(final Activation activation) throws ConsequenceException {
+        // We do this first as if a node modifies a fact that causes a recursion on an empty pattern
+        // we need to make sure it re-activates
+        increaseDormantActivations();
+
+        final EventSupport eventsupport = (EventSupport) this.workingMemory;
+
+        eventsupport.getAgendaEventSupport().fireBeforeActivationFired( activation,
+                                                                        this.workingMemory );
+
+        if ( activation.getActivationGroupNode() != null ) {
+            // We know that this rule will cancel all other activatiosn in the group
+            // so lets remove the information now, before the consequence fires
+            final ActivationGroup activationGroup = activation.getActivationGroupNode().getActivationGroup();
+            activationGroup.removeActivation( activation );
+            clearActivationGroup( activationGroup );
+        }
+        activation.setActivated( false );
+
+        try {
+            this.knowledgeHelper.setActivation( activation );
+            activation.getRule().getConsequence().evaluate( this.knowledgeHelper,
+                                                            this.workingMemory );
+            this.knowledgeHelper.reset();
+        } catch ( final Exception e ) {
+            this.consequenceExceptionHandler.handleException( activation, this.workingMemory, e );
+        }
+
+        if ( activation.getRuleFlowGroupNode() != null ) {
+            final InternalRuleFlowGroup ruleFlowGroup = activation.getRuleFlowGroupNode().getRuleFlowGroup();
+            ruleFlowGroup.removeActivation( activation );
+        }
+
+        eventsupport.getAgendaEventSupport().fireAfterActivationFired( activation, this.workingMemory );
+    }
+
+    public void increaseActiveActivations() {
+        this.activeActivations++;
+    }
+
+    public void decreaseActiveActivations() {
+        this.activeActivations--;
+    }
+
+    public void increaseDormantActivations() {
+        this.activeActivations--;
+        this.dormantActivations++;
+    }
+
+    public void decreaseDormantActivations() {
+        this.dormantActivations--;
+    }
+
+    public int getActiveActivations() {
+        return this.activeActivations;
+    }
+
+    public int getDormantActivations() {
+        return this.dormantActivations;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/DefaultBetaConstraints.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/DefaultBetaConstraints.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/DefaultBetaConstraints.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,298 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.RuleBaseConfiguration;
+import org.drools.base.evaluators.Operator;
+import org.drools.reteoo.BetaMemory;
+import org.drools.reteoo.FactHandleMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.reteoo.TupleMemory;
+import org.drools.rule.ContextEntry;
+import org.drools.rule.VariableConstraint;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.spi.Constraint;
+import org.drools.util.FactHandleIndexHashTable;
+import org.drools.util.FactHashTable;
+import org.drools.util.FactList;
+import org.drools.util.LinkedList;
+import org.drools.util.LinkedListEntry;
+import org.drools.util.TupleHashTable;
+import org.drools.util.TupleIndexHashTable;
+import org.drools.util.AbstractHashTable.FieldIndex;
+
+public class DefaultBetaConstraints
+    implements
+    Serializable,
+    BetaConstraints {
+
+    /**
+     * 
+     */
+    private static final long     serialVersionUID = 400L;
+
+    private final LinkedList      constraints;
+
+    private ContextEntry          contexts;
+
+    private int                   indexed;
+
+    public DefaultBetaConstraints(final BetaNodeFieldConstraint[] constraints,
+                                  final RuleBaseConfiguration conf) {
+        this( constraints, conf, false );
+        
+    }
+    
+    public DefaultBetaConstraints(final BetaNodeFieldConstraint[] constraints,
+                                  final RuleBaseConfiguration conf,
+                                  final boolean disableIndexing ) {
+        this.indexed = -1;
+        this.constraints = new LinkedList();
+        ContextEntry current = null;
+        final int depth = conf.getCompositeKeyDepth();
+
+        // First create a LinkedList of constraints, with the indexed constraints first.
+        for ( int i = 0, length = constraints.length; i < length; i++ ) {
+            // Determine  if this constraint is indexable
+            if ( (!disableIndexing) && conf.isIndexLeftBetaMemory() && conf.isIndexRightBetaMemory() && isIndexable( constraints[i] ) && ( this.indexed < depth-1 ) ) {
+                if ( depth >= 1 && this.indexed == -1 ) {
+                    // first index, so just add to the front
+                    this.constraints.insertAfter( null,
+                                                  new LinkedListEntry( constraints[i] ) );
+                    this.indexed++;
+                } else { 
+                    // insert this index after  the previous index
+                    this.constraints.insertAfter( findNode( this.indexed++ ),
+                                                  new LinkedListEntry( constraints[i] ) );
+                }
+            } else {
+                // not indexed, so just add to the  end
+                this.constraints.add( new LinkedListEntry( constraints[i] ) );
+            }
+        }
+
+        // Now create the ContextEntries  in the same order the constraints
+        for ( LinkedListEntry entry = (LinkedListEntry) this.constraints.getFirst(); entry != null; entry = (LinkedListEntry) entry.getNext() ) {
+            final BetaNodeFieldConstraint constraint = (BetaNodeFieldConstraint) entry.getObject();
+            final ContextEntry context = constraint.getContextEntry();
+            if ( current == null ) {
+                current = context;
+                this.contexts = context;
+            } else {
+                current.setNext( context );
+            }
+            current = context;
+        }
+    }
+
+    private LinkedListEntry findNode(final int pos) {
+        LinkedListEntry current = (LinkedListEntry) this.constraints.getFirst();
+        for ( int i = 0; i < pos; i++ ) {
+            current = (LinkedListEntry) current.getNext();
+        }
+        return current;
+    }
+
+    private ContextEntry findContext(final int pos) {
+        ContextEntry current = this.contexts;
+        for ( int i = 0; i < pos; i++ ) {
+            current = current.getNext();
+        }
+        return current;
+    }
+
+    private boolean isIndexable(final BetaNodeFieldConstraint constraint) {
+        if ( constraint instanceof VariableConstraint ) {
+            final VariableConstraint variableConstraint = (VariableConstraint) constraint;
+            return (variableConstraint.getEvaluator().getOperator() == Operator.EQUAL);
+        } else {
+            return false;
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#updateFromTuple(org.drools.reteoo.ReteTuple)
+     */
+    public void updateFromTuple(final InternalWorkingMemory workingMemory,
+                                final ReteTuple tuple) {
+        for ( ContextEntry context = this.contexts; context != null; context = context.getNext() ) {
+            context.updateFromTuple( workingMemory,
+                                     tuple );
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#updateFromFactHandle(org.drools.common.InternalFactHandle)
+     */
+    public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
+                                     final InternalFactHandle handle) {
+        for ( ContextEntry context = this.contexts; context != null; context = context.getNext() ) {
+            context.updateFromFactHandle( workingMemory,
+                                          handle );
+        }
+    }
+    
+    public void resetTuple() {
+        for ( ContextEntry context = this.contexts; context != null; context = context.getNext() ) {
+            context.resetTuple();
+        }
+    }
+    
+    public void resetFactHandle() {
+        for ( ContextEntry context = this.contexts; context != null; context = context.getNext() ) {
+            context.resetFactHandle();
+        }
+    }     
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#isAllowedCachedLeft(java.lang.Object)
+     */
+    public boolean isAllowedCachedLeft(final InternalFactHandle handle) {
+        // skip the indexed constraints
+        LinkedListEntry entry = (LinkedListEntry) findNode( this.indexed );
+
+        ContextEntry context = findContext( this.indexed );
+        while ( entry != null ) {
+            if ( !((BetaNodeFieldConstraint) entry.getObject()).isAllowedCachedLeft( context,
+                                                                                     handle ) ) {
+                return false;
+            }
+            entry = (LinkedListEntry) entry.getNext();
+            context = context.getNext();
+        }
+        return true;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#isAllowedCachedRight(org.drools.reteoo.ReteTuple)
+     */
+    public boolean isAllowedCachedRight(final ReteTuple tuple) {
+        // skip the indexed constraints
+        LinkedListEntry entry = (LinkedListEntry) findNode( this.indexed );
+
+        ContextEntry context = findContext( this.indexed );
+        while ( entry != null ) {
+            if ( !((BetaNodeFieldConstraint) entry.getObject()).isAllowedCachedRight( tuple,
+                                                                                      context ) ) {
+                return false;
+            }
+            entry = (LinkedListEntry) entry.getNext();
+            context = context.getNext();
+        }
+        return true;
+    }
+
+    public boolean isIndexed() {
+        // false if -1
+        return this.indexed >= 0;
+    }
+    
+    public int getIndexCount() {
+        return this.indexed+1;
+    }   
+
+    public boolean isEmpty() {
+        return false;
+    }
+
+    public BetaMemory createBetaMemory(RuleBaseConfiguration config) {
+        BetaMemory memory;
+        if ( this.indexed >= 0 ) {
+            LinkedListEntry entry = (LinkedListEntry) this.constraints.getFirst();
+            final List list = new ArrayList();
+
+            for ( int pos = 0; pos <= this.indexed; pos++ ) {
+                final Constraint constraint = (Constraint) entry.getObject();
+                final VariableConstraint variableConstraint = (VariableConstraint) constraint;
+                final FieldIndex index = new FieldIndex( variableConstraint.getFieldExtractor(),
+                                                         variableConstraint.getRequiredDeclarations()[0],
+                                                         variableConstraint.getEvaluator() );
+                list.add( index );
+                entry = (LinkedListEntry) entry.getNext();
+            }
+
+            final FieldIndex[] indexes = (FieldIndex[]) list.toArray( new FieldIndex[list.size()] );
+            TupleMemory tupleMemory;
+            if ( config.isIndexLeftBetaMemory() ) {
+                tupleMemory = new TupleIndexHashTable( indexes );
+            } else {
+                tupleMemory = new TupleHashTable();
+            }
+
+            FactHandleMemory factHandleMemory;
+            if ( config.isIndexRightBetaMemory() ) {
+                factHandleMemory = new FactHandleIndexHashTable( indexes );
+            } else {
+                factHandleMemory = config.isSequential() ? (FactHandleMemory) new FactList() : (FactHandleMemory) new FactHashTable();
+            }
+            memory = new BetaMemory( config.isSequential() ? null : tupleMemory,
+                                     factHandleMemory );
+        } else {
+            memory = new BetaMemory( config.isSequential() ? null : new TupleHashTable(),
+                                     config.isSequential() ? (FactHandleMemory) new FactList() : (FactHandleMemory) new FactHashTable() );
+        }
+
+        return memory;
+    }
+
+    public int hashCode() {
+        return this.constraints.hashCode();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#getConstraints()
+     */
+    public LinkedList getConstraints() {
+        return this.constraints;
+    }
+
+    /**
+     * Determine if another object is equal to this.
+     * 
+     * @param object
+     *            The object to test.
+     * 
+     * @return <code>true</code> if <code>object</code> is equal to this,
+     *         otherwise <code>false</code>.
+     */
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof DefaultBetaConstraints) ) {
+            return false;
+        }
+
+        final DefaultBetaConstraints other = (DefaultBetaConstraints) object;
+
+        if ( this.constraints == other.constraints ) {
+            return true;
+        }
+
+        if ( this.constraints.size() != other.constraints.size() ) {
+            return false;
+        }
+
+        return this.constraints.equals( other );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/DefaultFactHandle.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/DefaultFactHandle.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/DefaultFactHandle.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,173 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.FactHandle;
+
+/**
+ * Implementation of <code>FactHandle</code>.
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter </a>
+ */
+public class DefaultFactHandle
+    implements
+    InternalFactHandle {
+    // ----------------------------------------------------------------------
+    // Instance members
+    // ----------------------------------------------------------------------
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+    /** Handle id. */
+    private long              id;
+    private long              recency;
+    private Object            object;
+    private EqualityKey       key;
+    private int               objectHashCode;
+    private boolean           shadowFact;
+
+    // ----------------------------------------------------------------------
+    // Constructors
+    // ----------------------------------------------------------------------
+
+    public DefaultFactHandle() {
+
+    }
+
+    public DefaultFactHandle(final long id,
+                             final Object object) {
+        this( id,
+              object,
+              id );
+    }
+
+    /**
+     * Construct.
+     * 
+     * @param id
+     *            Handle id.
+     */
+    public DefaultFactHandle(final long id,
+                             final Object object,
+                             final long recency) {
+        this.id = id;
+        this.recency = recency;
+        this.object = object;
+        this.objectHashCode = object.hashCode();
+    }
+
+    // ----------------------------------------------------------------------
+    // Instance members
+    // ----------------------------------------------------------------------
+
+    /**
+     * @see Object
+     */
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof DefaultFactHandle) ) {
+            return false;
+        }
+
+        return this.id == ((DefaultFactHandle) object).id;
+    }
+
+    public int getObjectHashCode() {
+        return this.objectHashCode;
+    }
+
+    /**
+     * @see Object
+     */
+    public int hashCode() {
+        return (int) (this.id ^ (this.id >>> 32));
+    }
+
+    /**
+     * @see FactHandle
+     */
+    public String toExternalForm() {
+        return "[fact fid:" + this.id + ":" + this.recency + ":" + this.object + "]";
+    }
+
+    /**
+     * @see Object
+     */
+    public String toString() {
+        return toExternalForm();
+    }
+
+    public long getRecency() {
+        return this.recency;
+    }
+
+    public void setRecency(final long recency) {
+        this.recency = recency;
+    }
+
+    public long getId() {
+        return this.id;
+    }
+
+    public void invalidate() {
+        this.id = -1;
+        this.object = null;
+    }
+
+    public boolean isShadowFact() {
+        return this.shadowFact;
+    }
+
+    public void setShadowFact(final boolean shadowFact) {
+        this.shadowFact = shadowFact;
+    }
+
+    public Object getObject() {
+        return this.object;
+    }
+
+    public void setObject(final Object object) {
+        this.object = object;
+    }
+
+    /**
+     * @return the key
+     */
+    public EqualityKey getEqualityKey() {
+        return this.key;
+    }
+
+    /**
+     * @param key the key to set
+     */
+    public void setEqualityKey(final EqualityKey key) {
+        this.key = key;
+    }
+
+    /**
+     * Always returns false, since the DefaultFactHandle is
+     * only used for regular Facts, and not for Events
+     */
+    public boolean isEvent() {
+        return false;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/DoubleBetaConstraints.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/DoubleBetaConstraints.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/DoubleBetaConstraints.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,281 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.RuleBaseConfiguration;
+import org.drools.base.evaluators.Operator;
+import org.drools.reteoo.BetaMemory;
+import org.drools.reteoo.FactHandleMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.reteoo.TupleMemory;
+import org.drools.rule.ContextEntry;
+import org.drools.rule.VariableConstraint;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.util.FactHandleIndexHashTable;
+import org.drools.util.FactHashTable;
+import org.drools.util.FactList;
+import org.drools.util.LinkedList;
+import org.drools.util.LinkedListEntry;
+import org.drools.util.TupleHashTable;
+import org.drools.util.TupleIndexHashTable;
+import org.drools.util.AbstractHashTable.FieldIndex;
+
+public class DoubleBetaConstraints
+    implements
+    Serializable,
+    BetaConstraints {
+
+    /**
+     * 
+     */
+    private static final long             serialVersionUID = 400L;
+
+    private final BetaNodeFieldConstraint constraint0;
+    private final BetaNodeFieldConstraint constraint1;
+
+    private ContextEntry                  context0;
+    private ContextEntry                  context1;
+
+    private boolean                       indexed0;
+    private boolean                       indexed1;
+
+    public DoubleBetaConstraints(final BetaNodeFieldConstraint[] constraints,
+                                 final RuleBaseConfiguration conf) {
+        this( constraints,
+              conf,
+              false );
+    }
+
+    public DoubleBetaConstraints(final BetaNodeFieldConstraint[] constraints,
+                                 final RuleBaseConfiguration conf,
+                                 final boolean disableIndexing) {
+        if ( disableIndexing || (!conf.isIndexLeftBetaMemory() && !conf.isIndexRightBetaMemory()) ) {
+            this.indexed0 = false;
+            this.indexed1 = false;
+        } else {
+            final int depth = conf.getCompositeKeyDepth();
+
+            // Determine  if this constraints are indexable           
+            final boolean i0 = isIndexable( constraints[0] );
+            final boolean i1 = isIndexable( constraints[1] );
+
+            if ( depth >= 1 && i0 ) {
+                this.indexed0 = true;
+            }
+
+            if ( i1 ) {
+                if ( depth >= 1 && !i0 ) {
+                    this.indexed0 = true;
+                    swap( constraints,
+                          1,
+                          0 );
+                } else if ( depth >= 2 ) {
+                    this.indexed1 = true;
+                }
+            }
+        }
+
+        this.constraint0 = constraints[0];
+        this.context0 = this.constraint0.getContextEntry();
+
+        this.constraint1 = constraints[1];
+        this.context1 = this.constraint1.getContextEntry();
+    }
+
+    private void swap(final BetaNodeFieldConstraint[] constraints,
+                      final int p1,
+                      final int p2) {
+        final BetaNodeFieldConstraint temp = constraints[p2];
+        constraints[p2] = constraints[p1];
+        constraints[p1] = temp;
+    }
+
+    private boolean isIndexable(final BetaNodeFieldConstraint constraint) {
+        if ( constraint instanceof VariableConstraint ) {
+            final VariableConstraint variableConstraint = (VariableConstraint) constraint;
+            return (variableConstraint.getEvaluator().getOperator() == Operator.EQUAL);
+        } else {
+            return false;
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#updateFromTuple(org.drools.reteoo.ReteTuple)
+     */
+    public void updateFromTuple(final InternalWorkingMemory workingMemory,
+                                final ReteTuple tuple) {
+        this.context0.updateFromTuple( workingMemory,
+                                       tuple );
+        this.context1.updateFromTuple( workingMemory,
+                                       tuple );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#updateFromFactHandle(org.drools.common.InternalFactHandle)
+     */
+    public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
+                                     final InternalFactHandle handle) {
+        this.context0.updateFromFactHandle( workingMemory,
+                                            handle );
+        this.context1.updateFromFactHandle( workingMemory,
+                                            handle );
+    }
+    
+    public void resetTuple() {
+        this.context0.resetTuple();
+        this.context1.resetTuple();
+    }
+    
+    public void resetFactHandle() {
+        this.context0.resetFactHandle();
+        this.context1.resetFactHandle();
+    }      
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#isAllowedCachedLeft(java.lang.Object)
+     */
+    public boolean isAllowedCachedLeft(final InternalFactHandle handle) {
+        return (this.indexed0 || this.constraint0.isAllowedCachedLeft( this.context0,
+                                                                       handle )) && (this.indexed1 || this.constraint1.isAllowedCachedLeft( this.context1,
+                                                                                                                                            handle ));
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#isAllowedCachedRight(org.drools.reteoo.ReteTuple)
+     */
+    public boolean isAllowedCachedRight(final ReteTuple tuple) {
+        return this.constraint0.isAllowedCachedRight( tuple,
+                                                      this.context0 ) && this.constraint1.isAllowedCachedRight( tuple,
+                                                                                                                this.context1 );
+    }
+
+    public boolean isIndexed() {
+        return this.indexed0;
+    }
+
+    public int getIndexCount() {
+        int count = 0;
+        if ( this.indexed0 ) {
+            count++;
+        }
+        if ( this.indexed1 ) {
+            count++;
+        }
+        return count;
+    }
+
+    public boolean isEmpty() {
+        return false;
+    }
+
+    public BetaMemory createBetaMemory(final RuleBaseConfiguration config) {
+        BetaMemory memory;
+
+        final List list = new ArrayList( 2 );
+        if ( this.indexed0 ) {
+            final VariableConstraint variableConstraint = (VariableConstraint) this.constraint0;
+            final FieldIndex index = new FieldIndex( variableConstraint.getFieldExtractor(),
+                                                     variableConstraint.getRequiredDeclarations()[0],
+                                                     variableConstraint.getEvaluator() );
+            list.add( index );
+
+        }
+
+        if ( this.indexed1 ) {
+            final VariableConstraint variableConstraint = (VariableConstraint) this.constraint1;
+            final FieldIndex index = new FieldIndex( variableConstraint.getFieldExtractor(),
+                                                     variableConstraint.getRequiredDeclarations()[0],
+                                                     variableConstraint.getEvaluator() );
+            list.add( index );
+        }
+
+        if ( !list.isEmpty() ) {
+            final FieldIndex[] indexes = (FieldIndex[]) list.toArray( new FieldIndex[list.size()] );
+
+            TupleMemory tupleMemory;
+            if ( config.isIndexLeftBetaMemory() ) {
+                tupleMemory = new TupleIndexHashTable( indexes );
+            } else {
+                tupleMemory = new TupleHashTable();
+            }
+
+            FactHandleMemory factHandleMemory;
+            if ( config.isIndexRightBetaMemory() ) {
+                factHandleMemory = new FactHandleIndexHashTable( indexes );
+            } else {
+                factHandleMemory = config.isSequential() ? (FactHandleMemory) new FactList() : (FactHandleMemory) new FactHashTable();
+            }
+            memory = new BetaMemory( config.isSequential() ? null : tupleMemory,
+                                     factHandleMemory );
+        } else {
+            memory = new BetaMemory( config.isSequential() ? null : new TupleHashTable(),
+                                     config.isSequential() ? (FactHandleMemory) new FactList() : (FactHandleMemory) new FactHashTable() );
+        }
+
+        return memory;
+    }
+
+    public int hashCode() {
+        return this.constraint0.hashCode() ^ this.constraint1.hashCode();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#getConstraints()
+     */
+    public LinkedList getConstraints() {
+        final LinkedList list = new LinkedList();
+        list.add( new LinkedListEntry( this.constraint0 ) );
+        list.add( new LinkedListEntry( this.constraint1 ) );
+        return list;
+    }
+
+    /**
+     * Determine if another object is equal to this.
+     * 
+     * @param object
+     *            The object to test.
+     * 
+     * @return <code>true</code> if <code>object</code> is equal to this,
+     *         otherwise <code>false</code>.
+     */
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof DoubleBetaConstraints) ) {
+            return false;
+        }
+
+        final DoubleBetaConstraints other = (DoubleBetaConstraints) object;
+
+        if ( this.constraint0 != other.constraint0 && !this.constraint0.equals( other.constraint0 ) ) {
+            return false;
+        }
+
+        if ( this.constraint1 != other.constraint1 && !this.constraint1.equals( other.constraint1 ) ) {
+            return false;
+        }
+
+        return true;
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/DroolsObjectInputStream.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/DroolsObjectInputStream.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/DroolsObjectInputStream.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,120 @@
+/**
+ * 
+ */
+package org.drools.common;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamClass;
+import java.util.HashMap;
+
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.rule.Package;
+
+public class DroolsObjectInputStream extends ObjectInputStream {
+    private final ClassLoader        classLoader;
+    private InternalRuleBase         ruleBase;
+    private InternalWorkingMemory    workingMemory;
+    private Package                  pkg;
+    private ClassFieldExtractorCache extractorFactory;
+
+    /** table mapping primitive type names to corresponding class objects */
+    private static final HashMap     primClasses = new HashMap( 8,
+                                                                1.0F );
+    static {
+        primClasses.put( "boolean",
+                         boolean.class );
+        primClasses.put( "byte",
+                         byte.class );
+        primClasses.put( "char",
+                         char.class );
+        primClasses.put( "short",
+                         short.class );
+        primClasses.put( "int",
+                         int.class );
+        primClasses.put( "long",
+                         long.class );
+        primClasses.put( "float",
+                         float.class );
+        primClasses.put( "double",
+                         double.class );
+        primClasses.put( "void",
+                         void.class );
+    }
+
+    public DroolsObjectInputStream(final InputStream in) throws IOException {
+        this( in,
+              null );
+    }
+
+    public DroolsObjectInputStream(final InputStream in,
+                                   ClassLoader classLoader) throws IOException {
+        super( in );
+        if ( classLoader == null ) {
+            classLoader = Thread.currentThread().getContextClassLoader();
+            if ( classLoader == null ) {
+                classLoader = this.getClass().getClassLoader();
+            }
+        }
+
+        this.classLoader = classLoader;
+        this.extractorFactory = ClassFieldExtractorCache.getInstance();
+        enableResolveObject( true );
+    }
+
+    public ClassLoader getClassLoader() {
+        return this.classLoader;
+    }
+
+    protected Class resolveClass(final ObjectStreamClass desc) throws IOException,
+                                                              ClassNotFoundException {
+        if ( this.classLoader == null ) {
+            return super.resolveClass( desc );
+        } else {
+            final String name = desc.getName();
+            Class clazz = (Class) primClasses.get( name );
+            if ( clazz == null ) {
+                try {
+                    clazz = this.classLoader.loadClass( name );
+                } catch ( final ClassNotFoundException cnf ) {
+                    clazz = super.resolveClass( desc );
+                }
+            }
+            return clazz;
+        }
+    }
+
+    public InternalRuleBase getRuleBase() {
+        return ruleBase;
+    }
+
+    public void setRuleBase(InternalRuleBase ruleBase) {
+        this.ruleBase = ruleBase;
+    }
+
+    public void setWorkingMemory(InternalWorkingMemory workingMemory) {
+        this.workingMemory = workingMemory;
+    }
+
+    public InternalWorkingMemory getWorkingMemory() {
+        return workingMemory;
+    }
+
+    public Package getPackage() {
+        return pkg;
+    }
+
+    public void setPackage(Package pkg) {
+        this.pkg = pkg;
+    }
+
+    public ClassFieldExtractorCache getExtractorFactory() {
+        return extractorFactory;
+    }
+
+    public void setExtractorFactory(ClassFieldExtractorCache extractorFactory) {
+        this.extractorFactory = extractorFactory;
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EmptyBetaConstraints.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EmptyBetaConstraints.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EmptyBetaConstraints.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,131 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.drools.RuleBaseConfiguration;
+import org.drools.reteoo.BetaMemory;
+import org.drools.reteoo.FactHandleMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.util.FactHashTable;
+import org.drools.util.FactList;
+import org.drools.util.LinkedList;
+import org.drools.util.TupleHashTable;
+
+public class EmptyBetaConstraints
+    implements
+    Serializable,
+    BetaConstraints {
+
+    private static final BetaConstraints INSTANCE = new EmptyBetaConstraints();
+
+    public static BetaConstraints getInstance() {
+        return EmptyBetaConstraints.INSTANCE;
+    }
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    private EmptyBetaConstraints() {
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#updateFromTuple(org.drools.reteoo.ReteTuple)
+     */
+    public void updateFromTuple(final InternalWorkingMemory workingMemory,
+                                final ReteTuple tuple) {
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#updateFromFactHandle(org.drools.common.InternalFactHandle)
+     */
+    public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
+                                     final InternalFactHandle handle) {
+    }
+
+    public void resetTuple() {
+    }
+    
+    public void resetFactHandle() {
+    } 
+    
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#isAllowedCachedLeft(java.lang.Object)
+     */
+    public boolean isAllowedCachedLeft(final InternalFactHandle handle) {
+        return true;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#isAllowedCachedRight(org.drools.reteoo.ReteTuple)
+     */
+    public boolean isAllowedCachedRight(final ReteTuple tuple) {
+        return true;
+    }
+
+    public boolean isIndexed() {
+        return false;
+    }
+    
+    public int getIndexCount() {
+        return 0;
+    }
+
+    public boolean isEmpty() {
+        return true;
+    }
+
+    public BetaMemory createBetaMemory(final RuleBaseConfiguration config) {
+        final BetaMemory memory = new BetaMemory( config.isSequential() ? null : new TupleHashTable(),
+                                                  config.isSequential() ? (FactHandleMemory) new FactList() : (FactHandleMemory) new FactHashTable() );
+
+        return memory;
+    }
+
+    public int hashCode() {
+        return 1;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#getConstraints()
+     */
+    public LinkedList getConstraints() {
+        final LinkedList list = new LinkedList();
+        return list;
+    }
+
+    /**
+     * Determine if another object is equal to this.
+     * 
+     * @param object
+     *            The object to test.
+     * 
+     * @return <code>true</code> if <code>object</code> is equal to this,
+     *         otherwise <code>false</code>.
+     */
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        return (object != null && (object instanceof EmptyBetaConstraints));
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EqualityAssertMapComparator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EqualityAssertMapComparator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EqualityAssertMapComparator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,74 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.FactHandle;
+import org.drools.base.ShadowProxy;
+import org.drools.util.AbstractHashTable.ObjectComparator;
+
+public class EqualityAssertMapComparator
+    implements
+    ObjectComparator {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    public EqualityAssertMapComparator() {
+    }
+
+    public int hashCodeOf(final Object obj) {
+        if ( obj instanceof FactHandle ) {
+            return rehash( ((InternalFactHandle) obj).getObjectHashCode() );
+        }
+        return rehash( obj.hashCode() );
+    }
+
+    public int rehash(int h) {
+        h += ~(h << 9);
+        h ^= (h >>> 14);
+        h += (h << 4);
+        h ^= (h >>> 10);
+        return h;
+    }
+
+    /**
+     * Special comparator  that  allows FactHandles to  be  keys, but always  checks
+     * equals with the  identity of the  objects involved
+     */
+    public boolean equal(final Object o1,
+                         Object o2) {
+        if ( o1 instanceof FactHandle ) {
+            return o1 == o2;
+        }
+
+        final InternalFactHandle handle = ((InternalFactHandle) o2);
+
+        o2 = (handle.isShadowFact()) ? ((ShadowProxy) handle.getObject()).getShadowedObject() : handle.getObject();
+
+        return o1 == o2 || o1.equals( o2 );
+    }
+
+    public int compare(final Object o1,
+                       final Object o2) {
+        return ((Comparable) o1).compareTo( o2 );
+    }
+
+    public String toString() {
+        return "equality";
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EqualityKey.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EqualityKey.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EqualityKey.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,162 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.base.ShadowProxy;
+
+/**
+ * Upon instantiation the EqualityKey caches the first Object's hashCode
+ * this can never change. The EqualityKey has an internal datastructure 
+ * which references all the handles which are equal. It also records
+ * Whether the referenced facts are JUSTIFIED or STATED
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ *
+ */
+public class EqualityKey
+    implements
+    Serializable {
+    public final static int    STATED    = 1;
+    public final static int    JUSTIFIED = 2;
+
+    /** this is an optimisation so single stated equalities can tracked  without the overhead of  an ArrayList */
+    private InternalFactHandle handle;
+
+    /** this is always lazily maintainned  and deleted  when empty to minimise memory consumption */
+    private List               instances;
+
+    /** This is cached in the constructor from the first added Object */
+    private final int          hashCode;
+
+    /** Tracks whether this Fact is Stated or Justified */
+    private int                status;
+
+    public EqualityKey(final InternalFactHandle handle) {
+        this.handle = handle;
+        this.hashCode = handle.getObjectHashCode();
+    }
+
+    public EqualityKey(final InternalFactHandle handle,
+                       final int status) {
+        this.handle = handle;
+        this.hashCode = handle.getObjectHashCode();
+        this.status = status;
+    }
+
+    public InternalFactHandle getFactHandle() {
+        return this.handle;
+    }
+
+    public List getOtherFactHandle() {
+        return this.instances;
+    }
+
+    public void addFactHandle(final InternalFactHandle handle) {
+        if ( this.instances == null ) {
+            this.instances = new ArrayList();
+        }
+        this.instances.add( handle );
+    }
+
+    public void removeFactHandle(final InternalFactHandle handle) {
+        if ( this.handle == handle ) {
+            if ( this.instances == null ) {
+                this.handle = null;
+            } else {
+                this.handle = (InternalFactHandle) this.instances.remove( 0 );
+                if ( this.instances.isEmpty() ) {
+                    this.instances = null;
+                }                
+            }
+        } else {
+            this.instances.remove( handle );
+            if ( this.instances.isEmpty() ) {
+                this.instances = null;
+            }
+        }
+    }
+
+    /**
+     * @return the status
+     */
+    public int getStatus() {
+        return this.status;
+    }
+
+    /**
+     * @param status the status to set
+     */
+    public void setStatus(final int status) {
+        this.status = status;
+    }
+
+    public int size() {
+        if ( this.instances != null ) {
+            return this.instances.size() + 1;
+        } else {
+            return (this.handle != null) ? 1 : 0;
+        }
+    }
+
+    public boolean isEmpty() {
+        return (this.handle == null);
+    }
+
+    public String toString() {
+        String str = null;
+        switch ( this.status ) {
+            case 1 :
+                str = "STATED";
+                break;
+            case 2 :
+                str = "JUSTIFIED";
+                break;
+        }
+        return "[FactStatus status=" + this.status + "]";
+    }
+
+    /**
+     * Returns the cached hashCode
+     * @see java.lang.Object#hashCode()
+     */
+    public int hashCode() {
+        return this.hashCode;
+    }
+
+    /**
+     * Equality for the EqualityKey means two things. It returns 
+     * true if the object is also an EqualityKey the of the same
+     * the same identity as this. It also returns true if the object
+     * is equal to the head FactHandle's referenced Object. 
+     */
+    public boolean equals(final Object object) {
+        if ( object == null ) {
+            return false;
+        }
+
+        if ( object instanceof EqualityKey ) {
+            return this == object;
+        }
+        
+        return (this.handle.getObject().equals( object ));
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EqualityKeyComparator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EqualityKeyComparator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EqualityKeyComparator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,67 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.util.AbstractHashTable.ObjectComparator;
+
+public class EqualityKeyComparator
+    implements
+    ObjectComparator {
+    /**
+     * 
+     */
+    private static final long            serialVersionUID = 400L;
+
+    private static EqualityKeyComparator instance;
+
+    public static EqualityKeyComparator getInstance() {
+        if ( EqualityKeyComparator.instance == null ) {
+            EqualityKeyComparator.instance = new EqualityKeyComparator();
+        }
+
+        return EqualityKeyComparator.instance;
+    }
+
+    public int hashCodeOf(final Object key) {
+        return rehash( key.hashCode() );
+    }
+
+    public int rehash(int h) {
+        h += ~(h << 9);
+        h ^= (h >>> 14);
+        h += (h << 4);
+        h ^= (h >>> 10);
+        return h;
+    }
+
+    /**
+     * Equality key  reverses the compare, so  that  the  key  controls the  comparison
+     */
+    public boolean equal(final Object o1,
+                         final Object o2) {
+        return (o1 == null) ? (o2 == null) : (o1 == o2) || o2.equals( o1 );
+    }
+
+    public int compare(final Object o1,
+                       final Object o2) {
+        return ((Comparable) o1).compareTo( o2 );
+    }
+
+    public String toString() {
+        return "[EqualityKeyComparator]";
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EventFactHandle.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EventFactHandle.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EventFactHandle.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,148 @@
+package org.drools.common;
+
+import org.drools.FactHandle;
+
+public class EventFactHandle extends DefaultFactHandle {
+
+    private static final long serialVersionUID = 5997141759543399455L;
+    
+    private final long startTimestamp;
+    private final long endTimestamp;
+    private final long duration;
+
+    // ----------------------------------------------------------------------
+    // Constructors
+    // ----------------------------------------------------------------------
+
+    public EventFactHandle() {
+        super();
+        this.startTimestamp = 0;
+        this.endTimestamp = 0;
+        this.duration = 0;
+    }
+
+    public EventFactHandle(final long id,
+                           final Object object) {
+        super( id,
+               object );
+        this.startTimestamp = 0;
+        this.endTimestamp = 0;
+        this.duration = 0;
+    }
+
+    /**
+     * Construct.
+     * 
+     * @param id
+     *            Handle id.
+     */
+    public EventFactHandle(final long id,
+                           final Object object,
+                           final long recency) {
+        super( id,
+               object,
+               recency );
+        this.startTimestamp = 0;
+        this.endTimestamp = 0;
+        this.duration = 0;
+    }
+    
+    /**
+     * Creates a new event fact handle.
+     * 
+     * @param id this event fact handle ID
+     * @param object the event object encapsulated in this event fact handle
+     * @param recency the recency of this event fact handle
+     * @param timestamp the timestamp of the occurrence of this event
+     * @param duration the duration of this event. May be 0 (zero) in case this is a primitive event.
+     */
+    public EventFactHandle( final long id, 
+                            final Object object,
+                            final long recency,
+                            final long timestamp) {
+        super( id,
+               object, 
+               recency );
+        this.startTimestamp = timestamp;
+        this.endTimestamp = timestamp;
+        this.duration = 0;
+    }
+    
+    /**
+     * Creates a new event fact handle.
+     * 
+     * @param id this event fact handle ID
+     * @param object the event object encapsulated in this event fact handle
+     * @param recency the recency of this event fact handle
+     * @param timestamp the timestamp of the occurrence of this event
+     * @param duration the duration of this event. May be 0 (zero) in case this is a primitive event.
+     */
+    public EventFactHandle( final long id, 
+                            final Object object,
+                            final long recency,
+                            final long timestamp,
+                            final long duration ) {
+        super( id,
+               object, 
+               recency );
+        this.startTimestamp = timestamp-duration;
+        this.endTimestamp = timestamp;
+        this.duration = duration;
+    }
+    
+    /**
+     * @see FactHandle
+     */
+    public String toExternalForm() {
+        return "[event fid:" + getId() + ":" + getRecency() + ":" + getObject() + "]";
+    }
+
+    /**
+     * @see Object
+     */
+    public String toString() {
+        return toExternalForm();
+    }
+
+    /**
+     * Always returns true, since the EventFactHandle is
+     * only used for Events, and not for regular Facts
+     */
+    public boolean isEvent() {
+        return true;
+    }
+
+    /**
+     * Returns the start timestamp of the occurrence of this event.
+     * @return
+     */
+    public long getStartTimestamp() {
+        return startTimestamp;
+    }
+
+    /**
+     * Returns the duration of this event. In case this is a primitive event, 
+     * returns 0 (zero).
+     * 
+     * @return
+     */
+    public long getDuration() {
+        return duration;
+    }
+
+    /**
+     * Returns the end timestamp for this event.
+     * 
+     * @return
+     */
+    public long getEndTimestamp() {
+        return this.endTimestamp;
+    }
+    
+    /**
+     * Returns true for primitive events (i.e. duration 0), false otherwise (i.e. duration > 0)
+     */
+    public boolean isPrimitive() {
+        return duration==0;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EventSupport.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EventSupport.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/EventSupport.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,39 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.List;
+
+import org.drools.event.AgendaEventSupport;
+import org.drools.event.RuleFlowEventSupport;
+import org.drools.event.WorkingMemoryEventSupport;
+
+public interface EventSupport {
+	
+    List getAgendaEventListeners();
+
+    List getWorkingMemoryEventListeners();
+    
+    List getRuleFlowEventListeners();
+
+    AgendaEventSupport getAgendaEventSupport();
+    
+    WorkingMemoryEventSupport getWorkingMemoryEventSupport();
+
+    RuleFlowEventSupport getRuleFlowEventSupport();
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/IdentityAssertMapComparator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/IdentityAssertMapComparator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/IdentityAssertMapComparator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,79 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.FactHandle;
+import org.drools.base.ShadowProxy;
+import org.drools.util.AbstractHashTable.ObjectComparator;
+
+public class IdentityAssertMapComparator
+    implements
+    ObjectComparator {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    public IdentityAssertMapComparator() {
+    }
+
+    public int hashCodeOf(final Object obj) {
+        Object realObject = obj;
+        if ( realObject instanceof FactHandle ) {
+            realObject = ((InternalFactHandle) obj).getObject();
+        }
+        if ( realObject instanceof ShadowProxy ) {
+            realObject = ((ShadowProxy)realObject).getShadowedObject();
+        }
+        return rehash( System.identityHashCode( realObject ) );
+    }
+
+    public int rehash(int h) {
+        h += ~(h << 9);
+        h ^= (h >>> 14);
+        h += (h << 4);
+        h ^= (h >>> 10);
+        return h;
+    }
+
+    /**
+     * Special comparator that allows FactHandles to be keys, but always  checks
+     * like for like.
+     */
+    public boolean equal(final Object o1,
+                         final Object o2) {
+        if ( o1 instanceof FactHandle ) {
+            return ((InternalFactHandle) o1).getObject() == ((InternalFactHandle) o2).getObject();
+        }
+        Object left = o1;
+        if ( left instanceof ShadowProxy ) {
+            left = ((ShadowProxy)left).getShadowedObject();
+        }
+        final InternalFactHandle handle = ((InternalFactHandle) o2);
+
+        return left == ((handle.isShadowFact()) ? ((ShadowProxy) handle.getObject()).getShadowedObject() : handle.getObject());
+    }
+
+    public int compare(final Object o1,
+                       final Object o2) {
+        return ((Comparable) o1).compareTo( o2 );
+    }
+
+    public String toString() {
+        return "identity";
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InstanceEqualsConstraint.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InstanceEqualsConstraint.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InstanceEqualsConstraint.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.common;
+
+import org.drools.reteoo.ReteTuple;
+import org.drools.rule.Pattern;
+import org.drools.rule.ContextEntry;
+import org.drools.rule.Declaration;
+import org.drools.spi.BetaNodeFieldConstraint;
+
+/**
+ * InstanceEqualsConstraint
+ *
+ * Created: 21/06/2006
+ * @author <a href="mailto:tirelli at post.com">Edson Tirelli</a> 
+ *
+ * @version $Id$
+ */
+
+public class InstanceEqualsConstraint
+    implements
+    BetaNodeFieldConstraint {
+
+    private static final long   serialVersionUID = 400L;
+
+    private final Declaration[] declarations     = new Declaration[0];
+
+    private Pattern             otherPattern;
+
+    public InstanceEqualsConstraint(final Pattern otherPattern) {
+        this.otherPattern = otherPattern;
+    }
+
+    public Declaration[] getRequiredDeclarations() {
+        return this.declarations;
+    }
+
+    public void replaceDeclaration(Declaration oldDecl,
+                                   Declaration newDecl) {
+    }
+
+    public Pattern getOtherPattern() {
+        return this.otherPattern;
+    }
+
+    public ContextEntry getContextEntry() {
+        return new InstanceEqualsConstraintContextEntry( this.otherPattern );
+    }
+
+    public boolean isAllowedCachedLeft(final ContextEntry context,
+                                       final InternalFactHandle handle) {
+        return ((InstanceEqualsConstraintContextEntry) context).left == handle.getObject();
+    }
+
+    public boolean isAllowedCachedRight(final ReteTuple tuple,
+                                        final ContextEntry context) {
+        return tuple.get( this.otherPattern.getOffset() ).getObject() == ((InstanceEqualsConstraintContextEntry) context).right;
+    }
+
+    public String toString() {
+        return "[InstanceEqualsConstraint otherPattern=" + this.otherPattern + " ]";
+    }
+
+    public int hashCode() {
+        return this.otherPattern.hashCode();
+    }
+
+    public Object clone() {
+        // don't clone pattern
+        return new InstanceEqualsConstraint( this.otherPattern );
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof InstanceEqualsConstraint) ) {
+            return false;
+        }
+
+        final InstanceEqualsConstraint other = (InstanceEqualsConstraint) object;
+        return this.otherPattern.equals( other.otherPattern );
+    }
+
+    public static class InstanceEqualsConstraintContextEntry
+        implements
+        ContextEntry {
+
+        private static final long serialVersionUID = 400L;
+
+        public Object             left;
+        public Object             right;
+
+        private Pattern           pattern;
+        private ContextEntry      entry;
+
+        public InstanceEqualsConstraintContextEntry(final Pattern pattern) {
+            this.pattern = pattern;
+        }
+
+        public ContextEntry getNext() {
+            return this.entry;
+        }
+
+        public void setNext(final ContextEntry entry) {
+            this.entry = entry;
+        }
+
+        public void updateFromTuple(final InternalWorkingMemory workingMemory,
+                                    final ReteTuple tuple) {
+            this.left = tuple.get( this.pattern.getOffset() ).getObject();
+        }
+
+        public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
+                                         final InternalFactHandle handle) {
+            this.right = handle.getObject();
+        }
+        
+        public void resetTuple() {
+            this.left = null;
+        }
+        
+        public void resetFactHandle() {
+            this.right = null;
+        }         
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InstanceNotEqualsConstraint.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InstanceNotEqualsConstraint.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InstanceNotEqualsConstraint.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,137 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.reteoo.ReteTuple;
+import org.drools.rule.Pattern;
+import org.drools.rule.ContextEntry;
+import org.drools.rule.Declaration;
+import org.drools.spi.BetaNodeFieldConstraint;
+
+public class InstanceNotEqualsConstraint
+    implements
+    BetaNodeFieldConstraint {
+
+    private static final long          serialVersionUID = 400L;
+
+    private static final Declaration[] declarations     = new Declaration[0];
+
+    private Pattern                     otherPattern;
+
+    public InstanceNotEqualsConstraint(final Pattern otherPattern) {
+        this.otherPattern = otherPattern;
+    }
+
+    public Declaration[] getRequiredDeclarations() {
+        return InstanceNotEqualsConstraint.declarations;
+    }
+    
+    public void replaceDeclaration(Declaration oldDecl,
+                                   Declaration newDecl) {
+    }
+
+    public Pattern getOtherPattern() {
+        return this.otherPattern;
+    }
+
+    public ContextEntry getContextEntry() {
+        return new InstanceNotEqualsConstraintContextEntry( this.otherPattern );
+    }
+
+    public boolean isAllowed(final ContextEntry entry) {
+        final InstanceNotEqualsConstraintContextEntry context = (InstanceNotEqualsConstraintContextEntry) entry;
+        return context.left != context.right;
+    }
+
+    public boolean isAllowedCachedLeft(final ContextEntry context,
+                                       final InternalFactHandle handle) {
+        return ((InstanceNotEqualsConstraintContextEntry) context).left != handle.getObject();
+    }
+
+    public boolean isAllowedCachedRight(final ReteTuple tuple,
+                                        final ContextEntry context) {
+        return tuple.get( this.otherPattern.getOffset() ).getObject() != ((InstanceNotEqualsConstraintContextEntry) context).right;
+    }
+
+    public String toString() {
+        return "[InstanceEqualsConstraint otherPattern=" + this.otherPattern + " ]";
+    }
+
+    public int hashCode() {
+        return this.otherPattern.hashCode();
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof InstanceNotEqualsConstraint) ) {
+            return false;
+        }
+
+        final InstanceNotEqualsConstraint other = (InstanceNotEqualsConstraint) object;
+        return this.otherPattern.equals( other.otherPattern );
+    }
+    
+    public Object clone() {
+        return new InstanceNotEqualsConstraint( this.otherPattern );
+    }
+
+    public static class InstanceNotEqualsConstraintContextEntry
+        implements
+        ContextEntry {
+
+        private static final long serialVersionUID = 400L;
+        public Object             left;
+        public Object             right;
+
+        private Pattern            pattern;
+        private ContextEntry      entry;
+
+        public InstanceNotEqualsConstraintContextEntry(final Pattern pattern) {
+            this.pattern = pattern;
+        }
+
+        public ContextEntry getNext() {
+            return this.entry;
+        }
+
+        public void setNext(final ContextEntry entry) {
+            this.entry = entry;
+        }
+
+        public void updateFromTuple(final InternalWorkingMemory workingMemory,
+                                    final ReteTuple tuple) {
+            this.left = tuple.get( this.pattern.getOffset() ).getObject();
+        }
+
+        public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
+                                         final InternalFactHandle handle) {
+            this.right = handle.getObject();
+        }
+        
+        public void resetTuple() {
+            this.left = null;
+        }
+        
+        public void resetFactHandle() {
+            this.right = null;
+        }                
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalAgenda.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalAgenda.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalAgenda.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,35 @@
+package org.drools.common;
+
+import org.drools.Agenda;
+import org.drools.spi.Activation;
+import org.drools.spi.AgendaFilter;
+import org.drools.spi.AgendaGroup;
+import org.drools.spi.ConsequenceException;
+
+public interface InternalAgenda
+    extends
+    Agenda {
+
+    public void fireActivation(final Activation activation) throws ConsequenceException;
+
+    public void removeScheduleItem(final ScheduledAgendaItem item);
+
+    public boolean fireNextItem(AgendaFilter filter) throws ConsequenceException;
+
+    public void scheduleItem(final ScheduledAgendaItem item);
+
+    public void addAgendaGroup(final AgendaGroup agendaGroup);
+
+    public void increaseActiveActivations();
+
+    public void decreaseActiveActivations();
+
+    public void increaseDormantActivations();
+
+    public void decreaseDormantActivations();
+
+    public int getActiveActivations();
+
+    public int getDormantActivations();
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalAgendaGroup.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalAgendaGroup.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalAgendaGroup.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,16 @@
+package org.drools.common;
+
+import org.drools.spi.Activation;
+import org.drools.spi.AgendaGroup;
+
+public interface InternalAgendaGroup extends AgendaGroup {
+    public Activation getNext();
+    
+    public void add(Activation activation);
+    
+    public void setActive(boolean activate);
+    
+    public Activation[] getQueue();
+    
+    public void clear();        
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalFactHandle.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalFactHandle.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalFactHandle.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,54 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.FactHandle;
+
+public interface InternalFactHandle
+    extends
+    FactHandle {
+    public long getId();
+
+    public long getRecency();
+
+    public Object getObject();
+
+    public void setObject(Object object);
+
+    public void setEqualityKey(EqualityKey key);
+
+    public EqualityKey getEqualityKey();
+
+    public void setRecency(long recency);
+
+    public void invalidate();
+
+    public int getObjectHashCode();
+
+    public boolean isShadowFact();
+
+    public void setShadowFact(boolean shadowFact);
+    
+    /**
+     * Returns true if this FactHandle represents
+     * and Event or false if this FactHandle represents
+     * a regular Fact
+     * 
+     * @return
+     */
+    public boolean isEvent();
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalRuleBase.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalRuleBase.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalRuleBase.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,128 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Map;
+
+import org.drools.FactException;
+import org.drools.FactHandle;
+import org.drools.RuleBase;
+import org.drools.RuleBaseConfiguration;
+import org.drools.StatefulSession;
+import org.drools.objenesis.Objenesis;
+import org.drools.process.core.Process;
+import org.drools.reteoo.Rete;
+import org.drools.reteoo.ReteooWorkingMemory;
+import org.drools.rule.CompositePackageClassLoader;
+import org.drools.rule.MapBackedClassLoader;
+import org.drools.rule.Package;
+import org.drools.rule.TypeDeclaration;
+import org.drools.spi.FactHandleFactory;
+import org.drools.spi.PropagationContext;
+
+public interface InternalRuleBase
+    extends
+    RuleBase {
+
+    /**
+     * @return the id
+     */
+    public String getId();
+    
+    public int nextWorkingMemoryCounter();
+
+    public FactHandleFactory newFactHandleFactory();
+
+    public Map getGlobals();
+    
+    public Map getAgendaGroupRuleTotals();
+    
+    public RuleBaseConfiguration getConfiguration();
+    
+    public Package getPackage(String name);
+    
+    public Map getPackagesMap();
+
+    void disposeStatefulSession(StatefulSession statefulSession);
+    
+    void executeQueuedActions();
+
+    /**
+     * Assert a fact object.
+     * 
+     * @param handle
+     *            The handle.
+     * @param object
+     *            The fact.
+     * @param workingMemory
+     *            The working-memory.
+     * 
+     * @throws FactException
+     *             If an error occurs while performing the assertion.
+     */
+    public void assertObject(FactHandle handle,
+                             Object object,
+                             PropagationContext context,
+                             InternalWorkingMemory workingMemory) throws FactException;
+
+    /**
+     * Retract a fact object.
+     * 
+     * @param handle
+     *            The handle.
+     * @param workingMemory
+     *            The working-memory.
+     * 
+     * @throws FactException
+     *             If an error occurs while performing the retraction.
+     */
+    public void retractObject(FactHandle handle,
+                              PropagationContext context,
+                              ReteooWorkingMemory workingMemory) throws FactException;
+    
+    public void addClass(String className, byte[] bytes);
+    
+    public CompositePackageClassLoader getCompositePackageClassLoader();
+    
+    public MapBackedClassLoader getMapBackedClassLoader();
+    
+    public Rete getRete();
+    
+    public InternalWorkingMemory[] getWorkingMemories();
+    
+    public Process getProcess(String id);
+    
+    /**
+     * Returns true if clazz represents an Event class. False otherwise.
+     *  
+     * @param clazz
+     * @return
+     */
+    public boolean isEvent( Class clazz );
+
+	public Objenesis getObjenesis();
+	
+	public int getNodeCount();
+
+	/**
+	 * Returns the type declaration associated to the given class
+	 * 
+	 * @param clazz
+	 * @return
+	 */
+    public TypeDeclaration getTypeDeclaration(Class<?> clazz);
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalRuleFlowGroup.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalRuleFlowGroup.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalRuleFlowGroup.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,37 @@
+package org.drools.common;
+
+import org.drools.spi.Activation;
+import org.drools.spi.RuleFlowGroup;
+
+public interface InternalRuleFlowGroup extends RuleFlowGroup {
+
+	void setWorkingMemory(InternalWorkingMemory workingMemory);
+	
+	InternalWorkingMemory getWorkingMemory();
+	
+    void addActivation(Activation activation);
+
+    void removeActivation(final Activation activation);
+    
+    void clear();
+
+    /**
+     * Activates or deactivates this <code>RuleFlowGroup</code>.
+     * When activating, all activations of this <code>RuleFlowGroup</code> are added
+     * to the agenda.
+     * As long as the <code>RuleFlowGroup</code> remains active,
+     * its activations are automatically added to the agenda. 
+     * When deactivating, all activations of this <code>RuleFlowGroup</code> are removed
+     * to the agenda.
+     * As long as the <code>RuleFlowGroup</code> remains deactive,
+     * its activations are not added to the agenda. 
+     */
+    void setActive(boolean active);
+
+    boolean isActive();
+
+    void addRuleFlowGroupListener(RuleFlowGroupListener listener);
+    
+    void removeRuleFlowGroupListener(RuleFlowGroupListener listener);
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalWorkingMemory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalWorkingMemory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalWorkingMemory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,108 @@
+package org.drools.common;
+
+import java.util.Map;
+import java.util.concurrent.locks.Lock;
+
+import org.drools.FactException;
+import org.drools.FactHandle;
+import org.drools.WorkingMemory;
+import org.drools.event.AgendaEventSupport;
+import org.drools.event.RuleFlowEventSupport;
+import org.drools.event.WorkingMemoryEventSupport;
+import org.drools.process.instance.ProcessInstance;
+import org.drools.process.instance.ProcessInstanceFactory;
+import org.drools.reteoo.LIANodePropagation;
+import org.drools.reteoo.ObjectTypeConf;
+import org.drools.rule.EntryPoint;
+import org.drools.rule.Rule;
+import org.drools.rule.TimeMachine;
+import org.drools.spi.Activation;
+import org.drools.spi.FactHandleFactory;
+import org.drools.spi.PropagationContext;
+
+public interface InternalWorkingMemory
+    extends
+    WorkingMemory {
+    public long getId();
+    
+    public void setId(long id);
+    
+    void setRuleBase(final InternalRuleBase ruleBase);
+
+    public void setWorkingMemoryEventSupport(WorkingMemoryEventSupport workingMemoryEventSupport);
+
+    ///public ObjectHashMap getAssertMap();
+
+    public void setAgendaEventSupport(AgendaEventSupport agendaEventSupport);
+
+    public void setRuleFlowEventSupport(RuleFlowEventSupport ruleFlowEventSupport);
+    
+    public void registerProcessInstanceFactory(String type, ProcessInstanceFactory nodeInstanceFactory);
+
+    public Object getNodeMemory(NodeMemory node);
+
+    public void clearNodeMemory(NodeMemory node);
+
+    public long getNextPropagationIdCounter();
+
+    //public ObjectHashMap getFactHandleMap()
+    
+    public ObjectStore getObjectStore();
+
+    public TruthMaintenanceSystem getTruthMaintenanceSystem();
+
+    public void executeQueuedActions();
+
+    public void queueWorkingMemoryAction(final WorkingMemoryAction action);
+
+    public FactHandleFactory getFactHandleFactory();
+    
+    /**
+     * Looks for the fact handle associated to the given object
+     * by looking up the object IDENTITY (==), even if rule base
+     * is configured to AssertBehavior.EQUALITY.
+     * 
+     * @param object
+     * @return null if fact handle not found
+     */
+    public FactHandle getFactHandleByIdentity(final Object object);
+
+    public void removeLogicalDependencies(final Activation activation,
+                                          final PropagationContext context,
+                                          final Rule rule) throws FactException;
+
+    void retract(final FactHandle factHandle,
+                       final boolean removeLogical,
+                       final boolean updateEqualsMap,
+                       final Rule rule,
+                       final Activation activation) throws FactException;
+
+    public Lock getLock();
+
+    public boolean isSequential();
+
+    public void addLIANodePropagation(LIANodePropagation liaNodePropagation);
+
+	public TimeMachine getTimeMachine();
+
+	public void setTimeMachine(TimeMachine tm);
+    
+    public void removeProcessInstance(ProcessInstance processInstance);
+    
+    /**
+     * Returns the ObjectTypeConfiguration object for the given object
+     * or creates a new one if none is found in the cache
+     * 
+     * @param object
+     * @return
+     */
+    public ObjectTypeConf getObjectTypeConf(EntryPoint entryPoint, Object object);
+    
+    /**
+     * Returns the Map<Object key, ObjectTypeConf conf> of object type
+     * confs in this working memory
+     *  
+     * @return
+     */
+    public Map<Object, ObjectTypeConf> getObjectTypeConfMap(EntryPoint entryPoint);
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalWorkingMemoryActions.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalWorkingMemoryActions.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/InternalWorkingMemoryActions.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,56 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.FactException;
+import org.drools.FactHandle;
+import org.drools.rule.Rule;
+import org.drools.spi.Activation;
+
+public interface InternalWorkingMemoryActions
+    extends
+    InternalWorkingMemory {
+    public void update(FactHandle handle,
+                       Object object,
+                       Rule rule,
+                       Activation activation) throws FactException;
+
+    public void retract(FactHandle handle,
+                        boolean removeLogical,
+                        boolean updateEqualsMap,
+                        Rule rule,
+                        Activation activation) throws FactException;
+
+    FactHandle insert(Object object,
+                      boolean dynamic,
+                      boolean logical,
+                      Rule rule,
+                      Activation activation) throws FactException;
+    
+    public FactHandle insertLogical(Object object,
+                                    boolean dynamic) throws FactException;
+    
+    public void modifyRetract(final FactHandle factHandle,
+                              final Rule rule,
+                              final Activation activation);
+
+    public void modifyInsert(final FactHandle factHandle,
+                             final Object object,
+                             final Rule rule,
+                             final Activation activation);
+    
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/LogicalDependency.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/LogicalDependency.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/LogicalDependency.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,65 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.FactHandle;
+import org.drools.spi.Activation;
+import org.drools.util.AbstractBaseLinkedListNode;
+
+/**
+ * LogicalDependency is a special node for LinkedLists that maintains
+ * references for the Activation justifier and the justified FactHandle.
+ *   
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ *
+ */
+public class LogicalDependency extends AbstractBaseLinkedListNode {
+    private Activation justifier;
+    private FactHandle factHandle;
+
+    public LogicalDependency(final Activation justifier,
+                             final FactHandle factHandle) {
+        super();
+        this.justifier = justifier;
+        this.factHandle = factHandle;
+    }
+
+    public FactHandle getFactHandle() {
+        return this.factHandle;
+    }
+
+    public Activation getJustifier() {
+        return this.justifier;
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof LogicalDependency) ) {
+            return false;
+        }
+
+        final LogicalDependency other = (LogicalDependency) object;
+        return (this.getJustifier() == other.getJustifier() && this.getFactHandle() == other.getFactHandle());
+    }
+
+    public int hashCode() {
+        return this.justifier.hashCode();
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/NetworkNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/NetworkNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/NetworkNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,39 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+/**
+ * Interface used to expose generic information on Rete nodes outside of he package. It is used
+ * for exposing information events.
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ *
+ */
+public interface NetworkNode
+    extends
+    Serializable {
+
+    /**
+     * Returns the unique id that represents the node in the Rete network
+     * @return
+     *      unique int value
+     */
+    public int getId();
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/NodeMemories.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/NodeMemories.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/NodeMemories.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008 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.
+ *
+ * Created on Jan 15, 2008
+ */
+
+package org.drools.common;
+
+import java.io.Serializable;
+
+/**
+ * An interface for node memories implementation
+ * 
+ * @author etirelli
+ */
+public interface NodeMemories extends Serializable {
+    
+    public Object getNodeMemory( NodeMemory node );
+    
+    public void clearNodeMemory( NodeMemory node );
+
+    public void setRuleBaseReference(InternalRuleBase ruleBase);
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/NodeMemory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/NodeMemory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/NodeMemory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,26 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.RuleBaseConfiguration;
+
+public interface NodeMemory {
+    public int getId();
+
+    public Object createMemory(RuleBaseConfiguration config);
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ObjectStore.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ObjectStore.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ObjectStore.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,47 @@
+package org.drools.common;
+
+import java.util.Iterator;
+
+import org.drools.ObjectFilter;
+
+public interface ObjectStore {
+
+    public abstract int size();
+
+    public abstract boolean isEmpty();
+
+    public abstract Object getObjectForHandle(InternalFactHandle handle);
+
+    public abstract InternalFactHandle getHandleForObject(Object object);
+    
+    public abstract InternalFactHandle getHandleForObjectIdentity(Object object);
+
+    public abstract void updateHandle(InternalFactHandle handle,
+                                      Object object);
+
+    public abstract void addHandle(InternalFactHandle handle,
+                                   Object object);
+
+    public abstract void removeHandle(final InternalFactHandle handle);
+
+    /**
+     * This class is not thread safe, changes to the working memory during iteration may give unexpected results
+     */
+    public abstract Iterator iterateObjects();
+
+    /**
+     * This class is not thread safe, changes to the working memory during iteration may give unexpected results
+     */
+    public abstract Iterator iterateObjects(ObjectFilter filter);
+
+    /**
+     * This class is not thread safe, changes to the working memory during iteration may give unexpected results
+     */
+    public abstract Iterator iterateFactHandles();
+
+    /**
+     * This class is not thread safe, changes to the working memory during iteration may give unexpected results
+     */
+    public abstract Iterator iterateFactHandles(ObjectFilter filter);
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/PriorityQueueAgendaGroupFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/PriorityQueueAgendaGroupFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/PriorityQueueAgendaGroupFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,18 @@
+package org.drools.common;
+
+import java.io.Serializable;
+
+import org.drools.spi.AgendaGroup;
+
+public class PriorityQueueAgendaGroupFactory implements AgendaGroupFactory, Serializable {
+    private static final AgendaGroupFactory INSTANCE = new PriorityQueueAgendaGroupFactory();
+    
+    public static AgendaGroupFactory getInstance() {
+        return INSTANCE;
+    }
+    
+    public AgendaGroup createAgendaGroup(String name, InternalRuleBase ruleBase) {
+        return new BinaryHeapQueueAgendaGroup( name,
+                                    ruleBase );        
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/PropagationContextImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/PropagationContextImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/PropagationContextImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,188 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.reteoo.ReteTuple;
+import org.drools.rule.EntryPoint;
+import org.drools.rule.Rule;
+import org.drools.spi.Activation;
+import org.drools.spi.PropagationContext;
+import org.drools.util.ObjectHashMap;
+
+public class PropagationContextImpl
+    implements
+    PropagationContext {
+
+    private static final long serialVersionUID = 8400185220119865618L;
+
+    private int    		 type;
+    
+    private Rule         rule;
+
+    private Activation   activation;
+
+    private final long   propagationNumber;
+
+    public final int     activeActivations;
+
+    public final int     dormantActivations;
+
+    public ObjectHashMap retracted;
+
+    private EntryPoint   entryPoint;
+
+    public PropagationContextImpl(final long number,
+                                  final int type,
+                                  final Rule rule,
+                                  final Activation activation) {
+        this.type = type;
+        this.rule = rule;
+        this.activation = activation;
+        this.propagationNumber = number;
+        this.activeActivations = 0;
+        this.dormantActivations = 0;
+        this.entryPoint = EntryPoint.DEFAULT;
+    }
+
+    public PropagationContextImpl(final long number,
+                                  final int type,
+                                  final Rule rule,
+                                  final Activation activation,
+                                  final int activeActivations,
+                                  final int dormantActivations,
+                                  final EntryPoint entryPoint) {
+        this.type = type;
+        this.rule = rule;
+        this.activation = activation;
+        this.propagationNumber = number;
+        this.activeActivations = activeActivations;
+        this.dormantActivations = dormantActivations;
+        this.entryPoint = entryPoint;
+    }
+
+    public long getPropagationNumber() {
+        return this.propagationNumber;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.drools.reteoo.PropagationContext#getRuleOrigin()
+     */
+    public Rule getRuleOrigin() {
+        return this.rule;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.drools.reteoo.PropagationContext#getActivationOrigin()
+     */
+    public Activation getActivationOrigin() {
+        return this.activation;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.drools.reteoo.PropagationContext#getType()
+     */
+    public int getType() {
+        return this.type;
+    }
+
+    public int getActiveActivations() {
+        return this.activeActivations;
+    }
+
+    public int getDormantActivations() {
+        return this.dormantActivations;
+    }
+
+    public void addRetractedTuple(final Rule rule,
+                                  final Activation activation) {
+        if ( this.retracted == null ) {
+            this.retracted = new ObjectHashMap();
+        }
+
+        ReteTuple tuple = (ReteTuple) activation.getTuple();
+
+        ObjectHashMap tuples = (ObjectHashMap) this.retracted.get( rule );
+        if ( tuples == null ) {
+            tuples = new ObjectHashMap();
+            this.retracted.put( rule,
+                                tuples );
+        }
+        tuples.put( tuple,
+                    activation );
+    }
+
+    public Activation removeRetractedTuple(final Rule rule,
+                                           final ReteTuple tuple) {
+        if ( this.retracted == null ) {
+            return null;
+        }
+
+        final ObjectHashMap tuples = (ObjectHashMap) this.retracted.get( rule );
+        if ( tuples != null ) {
+            return (Activation) tuples.remove( tuple );
+        } else {
+            return null;
+        }
+    }
+
+    public void clearRetractedTuples() {
+        this.retracted = null;
+    }
+
+    public void releaseResources() {
+        this.activation = null;
+        this.retracted = null;
+        this.rule = null;
+    }
+
+    /**
+     * @return the entryPoint
+     */
+    public EntryPoint getEntryPoint() {
+        return entryPoint;
+    }
+
+    /**
+     * @param entryPoint the entryPoint to set
+     */
+    public void setEntryPoint(EntryPoint entryPoint) {
+        this.entryPoint = entryPoint;
+    }
+
+    /**
+     * @param clone the object and set new type
+     */
+    public PropagationContext clone(final int myType) {
+        return new PropagationContextImpl(propagationNumber,
+        								  myType,
+        								  rule,
+        								  activation,
+        								  activeActivations,
+        								  dormantActivations,
+        								  entryPoint);
+    }
+
+    public void setType (int type){
+    	this.type = type;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/QuadroupleBetaConstraints.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/QuadroupleBetaConstraints.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/QuadroupleBetaConstraints.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,389 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.RuleBaseConfiguration;
+import org.drools.base.evaluators.Operator;
+import org.drools.reteoo.BetaMemory;
+import org.drools.reteoo.FactHandleMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.reteoo.TupleMemory;
+import org.drools.rule.ContextEntry;
+import org.drools.rule.VariableConstraint;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.util.FactHandleIndexHashTable;
+import org.drools.util.FactHashTable;
+import org.drools.util.FactList;
+import org.drools.util.LinkedList;
+import org.drools.util.LinkedListEntry;
+import org.drools.util.TupleHashTable;
+import org.drools.util.TupleIndexHashTable;
+import org.drools.util.AbstractHashTable.FieldIndex;
+
+public class QuadroupleBetaConstraints
+    implements
+    Serializable,
+    BetaConstraints {
+
+    /**
+     * 
+     */
+    private static final long             serialVersionUID = 400L;
+
+    private final BetaNodeFieldConstraint constraint0;
+    private final BetaNodeFieldConstraint constraint1;
+    private final BetaNodeFieldConstraint constraint2;
+    private final BetaNodeFieldConstraint constraint3;
+
+    private final ContextEntry            context0;
+    private final ContextEntry            context1;
+    private final ContextEntry            context2;
+    private final ContextEntry            context3;
+
+    private boolean                       indexed0;
+    private boolean                       indexed1;
+    private boolean                       indexed2;
+    private boolean                       indexed3;
+
+    public QuadroupleBetaConstraints(final BetaNodeFieldConstraint[] constraints,
+                                     final RuleBaseConfiguration conf) {
+        this( constraints,
+              conf,
+              false );
+    }
+
+    public QuadroupleBetaConstraints(final BetaNodeFieldConstraint[] constraints,
+                                     final RuleBaseConfiguration conf,
+                                     final boolean disableIndexing) {
+        if ( disableIndexing || ( !conf.isIndexLeftBetaMemory() && !conf.isIndexRightBetaMemory() ) ) {
+            this.indexed0 = false;
+            this.indexed1 = false;
+            this.indexed2 = false;
+            this.indexed3 = false;
+        } else {
+            final int depth = conf.getCompositeKeyDepth();
+
+            // Determine  if this constraints are indexable                           
+            final boolean i0 = isIndexable( constraints[0] );
+            final boolean i1 = isIndexable( constraints[1] );
+            final boolean i2 = isIndexable( constraints[2] );
+            final boolean i3 = isIndexable( constraints[3] );
+
+            if ( depth >= 1 && i0 ) {
+                this.indexed0 = true;
+            }
+
+            if ( i1 ) {
+                if ( depth >= 1 && !this.indexed0 ) {
+                    this.indexed0 = true;
+                    swap( constraints,
+                          1,
+                          0 );
+                } else if ( depth >= 2 ) {
+                    this.indexed1 = true;
+                }
+            }
+
+            if ( i2 ) {
+                if ( depth >= 1 && !this.indexed0 ) {
+                    this.indexed0 = true;
+                    swap( constraints,
+                          2,
+                          0 );
+                } else if ( depth >= 2 && this.indexed0 && !this.indexed1 ) {
+                    this.indexed1 = true;
+                    swap( constraints,
+                          2,
+                          1 );
+                } else if ( depth >= 3 ) {
+                    this.indexed2 = true;
+                }
+            }
+
+            if ( i3 ) {
+                if ( depth >= 1 && !this.indexed0 ) {
+                    this.indexed0 = true;
+                    swap( constraints,
+                          3,
+                          0 );
+                } else if ( depth >= 2 && this.indexed0 && !this.indexed1 ) {
+                    this.indexed1 = true;
+                    swap( constraints,
+                          3,
+                          1 );
+                } else if ( depth >= 3 && this.indexed0 && this.indexed1 && !this.indexed2 ) {
+                    this.indexed2 = true;
+                    swap( constraints,
+                          3,
+                          2 );
+                } else if ( depth >= 4 ) {
+                    this.indexed3 = true;
+                }
+            }
+        }
+
+        this.constraint0 = constraints[0];
+        this.context0 = this.constraint0.getContextEntry();
+
+        this.constraint1 = constraints[1];
+        this.context1 = this.constraint1.getContextEntry();
+
+        this.constraint2 = constraints[2];
+        this.context2 = this.constraint2.getContextEntry();
+
+        this.constraint3 = constraints[3];
+        this.context3 = this.constraint3.getContextEntry();
+    }
+
+    private void swap(final BetaNodeFieldConstraint[] constraints,
+                      final int p1,
+                      final int p2) {
+        final BetaNodeFieldConstraint temp = constraints[p2];
+        constraints[p2] = constraints[p1];
+        constraints[p1] = temp;
+    }
+
+    private boolean isIndexable(final BetaNodeFieldConstraint constraint) {
+        if ( constraint instanceof VariableConstraint ) {
+            final VariableConstraint variableConstraint = (VariableConstraint) constraint;
+            return (variableConstraint.getEvaluator().getOperator() == Operator.EQUAL);
+        } else {
+            return false;
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#updateFromTuple(org.drools.reteoo.ReteTuple)
+     */
+    public void updateFromTuple(final InternalWorkingMemory workingMemory,
+                                final ReteTuple tuple) {
+        this.context0.updateFromTuple( workingMemory,
+                                       tuple );
+        this.context1.updateFromTuple( workingMemory,
+                                       tuple );
+        this.context2.updateFromTuple( workingMemory,
+                                       tuple );
+        this.context3.updateFromTuple( workingMemory,
+                                       tuple );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#updateFromFactHandle(org.drools.common.InternalFactHandle)
+     */
+    public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
+                                     final InternalFactHandle handle) {
+        this.context0.updateFromFactHandle( workingMemory,
+                                            handle );
+        this.context1.updateFromFactHandle( workingMemory,
+                                            handle );
+        this.context2.updateFromFactHandle( workingMemory,
+                                            handle );
+        this.context3.updateFromFactHandle( workingMemory,
+                                            handle );
+    }
+    
+    public void resetTuple() {
+        this.context0.resetTuple();
+        this.context1.resetTuple();
+        this.context2.resetTuple();
+        this.context3.resetTuple();
+    }
+    
+    public void resetFactHandle() {
+        this.context0.resetFactHandle();
+        this.context1.resetFactHandle();
+        this.context2.resetFactHandle();
+        this.context3.resetFactHandle();
+    }      
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#isAllowedCachedLeft(java.lang.Object)
+     */
+    public boolean isAllowedCachedLeft(final InternalFactHandle handle) {
+        //        return ( this.indexed0 || this.constraint0.isAllowedCachedLeft( context0,
+        //                                                                       object ) ) && this.constraint1.isAllowedCachedLeft( context1,
+        //                                                                                                       object ) && this.constraint2.isAllowedCachedLeft( context2,
+        //                                                                                                                                                         object );
+
+        return (this.indexed0 || this.constraint0.isAllowedCachedLeft( this.context0,
+                                                                       handle )) && (this.indexed1 || this.constraint1.isAllowedCachedLeft( this.context1,
+                                                                                                                                            handle )) && (this.indexed2 || this.constraint2.isAllowedCachedLeft( this.context2,
+                                                                                                                                                                                                                 handle ))
+               && (this.indexed3 || this.constraint3.isAllowedCachedLeft( this.context3,
+                                                                          handle ));
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#isAllowedCachedRight(org.drools.reteoo.ReteTuple)
+     */
+    public boolean isAllowedCachedRight(final ReteTuple tuple) {
+        return this.constraint0.isAllowedCachedRight( tuple,
+                                                      this.context0 ) && this.constraint1.isAllowedCachedRight( tuple,
+                                                                                                                this.context1 ) && this.constraint2.isAllowedCachedRight( tuple,
+                                                                                                                                                                          this.context2 )
+               && (this.indexed3 || this.constraint3.isAllowedCachedRight( tuple,
+                                                                           this.context3 ));
+    }
+
+    public boolean isIndexed() {
+        return this.indexed0;
+    }
+    
+    public int getIndexCount() {
+        int count = 0;
+        if ( this.indexed0 ) {
+            count++;
+        }
+        if ( this.indexed1 ) {
+            count++;
+        }
+        if ( this.indexed2 ) {
+            count++;
+        }
+        if ( this.indexed3 ) {
+            count++;
+        }        
+        return count;    
+    }     
+
+    public boolean isEmpty() {
+        return false;
+    }
+
+    public BetaMemory createBetaMemory(RuleBaseConfiguration conf) {
+
+        BetaMemory memory;
+
+        final List list = new ArrayList( 2 );
+        if ( this.indexed0 ) {
+            final VariableConstraint variableConstraint = (VariableConstraint) this.constraint0;
+            final FieldIndex index = new FieldIndex( variableConstraint.getFieldExtractor(),
+                                                     variableConstraint.getRequiredDeclarations()[0],
+                                                     variableConstraint.getEvaluator() );
+            list.add( index );
+
+        }
+
+        if ( this.indexed1 ) {
+            final VariableConstraint variableConstraint = (VariableConstraint) this.constraint1;
+            final FieldIndex index = new FieldIndex( variableConstraint.getFieldExtractor(),
+                                                     variableConstraint.getRequiredDeclarations()[0],
+                                                     variableConstraint.getEvaluator() );
+            list.add( index );
+        }
+
+        if ( this.indexed2 ) {
+            final VariableConstraint variableConstraint = (VariableConstraint) this.constraint2;
+            final FieldIndex index = new FieldIndex( variableConstraint.getFieldExtractor(),
+                                                     variableConstraint.getRequiredDeclarations()[0],
+                                                     variableConstraint.getEvaluator() );
+            list.add( index );
+        }
+
+        if ( this.indexed3 ) {
+            final VariableConstraint variableConstraint = (VariableConstraint) this.constraint3;
+            final FieldIndex index = new FieldIndex( variableConstraint.getFieldExtractor(),
+                                                     variableConstraint.getRequiredDeclarations()[0],
+                                                     variableConstraint.getEvaluator() );
+            list.add( index );
+        }
+
+        if ( !list.isEmpty() ) {
+            final FieldIndex[] indexes = (FieldIndex[]) list.toArray( new FieldIndex[list.size()] );
+            TupleMemory tupleMemory;
+            if ( conf.isIndexLeftBetaMemory() ) {
+                tupleMemory = new TupleIndexHashTable( indexes );
+            } else {
+                tupleMemory = new TupleHashTable();
+            }
+
+            FactHandleMemory factHandleMemory;
+            if ( conf.isIndexRightBetaMemory() ) {
+                factHandleMemory = new FactHandleIndexHashTable( indexes );
+            } else {
+                factHandleMemory = conf.isSequential() ? (FactHandleMemory) new FactList() : (FactHandleMemory) new FactHashTable();
+            }
+            memory = new BetaMemory( conf.isSequential() ? null : tupleMemory,
+                                     factHandleMemory );
+        } else {
+            memory = new BetaMemory( conf.isSequential() ? null : new TupleHashTable(),
+                                     conf.isSequential() ? (FactHandleMemory) new FactList() : (FactHandleMemory) new FactHashTable() );
+        }
+
+        return memory;
+    }
+
+    public int hashCode() {
+        return this.constraint0.hashCode() ^ this.constraint1.hashCode() ^ this.constraint2.hashCode() ^ this.constraint3.hashCode();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#getConstraints()
+     */
+    public LinkedList getConstraints() {
+        final LinkedList list = new LinkedList();
+        list.add( new LinkedListEntry( this.constraint0 ) );
+        list.add( new LinkedListEntry( this.constraint1 ) );
+        list.add( new LinkedListEntry( this.constraint2 ) );
+        list.add( new LinkedListEntry( this.constraint3 ) );
+        return list;
+    }
+
+    /**
+     * Determine if another object is equal to this.
+     * 
+     * @param object
+     *            The object to test.
+     * 
+     * @return <code>true</code> if <code>object</code> is equal to this,
+     *         otherwise <code>false</code>.
+     */
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof QuadroupleBetaConstraints) ) {
+            return false;
+        }
+
+        final QuadroupleBetaConstraints other = (QuadroupleBetaConstraints) object;
+
+        if ( this.constraint0 != other.constraint0 && !this.constraint0.equals( other.constraint0 ) ) {
+            return false;
+        }
+
+        if ( this.constraint1 != other.constraint1 && !this.constraint1.equals( other.constraint1 ) ) {
+            return false;
+        }
+
+        if ( this.constraint2 != other.constraint2 && !this.constraint2.equals( other.constraint2 ) ) {
+            return false;
+        }
+
+        if ( this.constraint3 != other.constraint3 && !this.constraint3.equals( other.constraint3 ) ) {
+            return false;
+        }
+
+        return true;
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/RuleFlowGroupImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/RuleFlowGroupImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/RuleFlowGroupImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,232 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.spi.Activation;
+import org.drools.util.Iterator;
+import org.drools.util.LinkedList;
+
+/**
+ * Implementation of a <code>RuleFlowGroup</code> that collects activations
+ * of rules of this ruleflow-group.
+ * If this group is activated, all its activations are added to the agenda.
+ * As long as this group is active, its activations are added to the agenda.
+ * Deactivating the group removes all its activations from the agenda and
+ * collects them until it is activated again.
+ * By default, <code>RuleFlowGroups</code> are automatically deactivated when there are no more
+ * activations in the <code>RuleFlowGroup</code>.  However, this can be configured.  
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ *
+ */
+public class RuleFlowGroupImpl implements InternalRuleFlowGroup {
+
+    private static final long     serialVersionUID = 400L;
+
+    private InternalWorkingMemory workingMemory;
+    private final String          name;
+    private boolean               active           = false;
+    private final LinkedList      list;
+    private boolean               autoDeactivate   = true;
+    private List<RuleFlowGroupListener> listeners;
+
+    /**
+     * Construct a <code>RuleFlowGroupImpl</code> with the given name.
+     * 
+     * @param name
+     *      The RuleFlowGroup name.
+     */
+    public RuleFlowGroupImpl(final String name) {
+        this.name = name;
+        this.list = new LinkedList();
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public void setWorkingMemory(InternalWorkingMemory workingMemory) {
+        this.workingMemory = workingMemory;
+    }
+
+    public InternalWorkingMemory getWorkingMemory() {
+        return this.workingMemory;
+    }
+
+    public void setActive(final boolean active) {
+        if ( this.active == active ) {
+            return;
+        }
+        this.active = active;
+        if ( active ) {
+            ((EventSupport) this.workingMemory).getRuleFlowEventSupport()
+                    .fireBeforeRuleFlowGroupActivated(this, this.workingMemory);
+            if ( this.list.isEmpty() ) {
+                if ( this.autoDeactivate ) {
+                    // if the list of activations is empty and
+                    // auto-deactivate is on, deactivate this group
+                    WorkingMemoryAction action = new DeactivateCallback( this );
+                    this.workingMemory.queueWorkingMemoryAction( action );
+                }
+            } else {
+                triggerActivations();
+            }
+            ((EventSupport) this.workingMemory).getRuleFlowEventSupport()
+                    .fireAfterRuleFlowGroupActivated(this, this.workingMemory);
+        } else {
+            ((EventSupport) this.workingMemory).getRuleFlowEventSupport()
+                    .fireBeforeRuleFlowGroupDeactivated(this, this.workingMemory);
+            final Iterator it = this.list.iterator();
+            for ( RuleFlowGroupNode node = (RuleFlowGroupNode) it.next(); node != null; node = (RuleFlowGroupNode) it.next() ) {
+                final Activation activation = node.getActivation();
+                activation.remove();
+                if ( activation.getActivationGroupNode() != null ) {
+                    activation.getActivationGroupNode().getActivationGroup().removeActivation( activation );
+                }
+            }
+            notifyRuleFlowGroupListeners();
+            ((EventSupport) this.workingMemory).getRuleFlowEventSupport()
+                    .fireAfterRuleFlowGroupDeactivated(this, this.workingMemory);
+        }
+    }
+
+    public boolean isActive() {
+        return this.active;
+    }
+
+    public boolean isAutoDeactivate() {
+        return this.autoDeactivate;
+    }
+
+    public void setAutoDeactivate(final boolean autoDeactivate) {
+        this.autoDeactivate = autoDeactivate;
+        if ( autoDeactivate && this.active && this.list.isEmpty() ) {
+            this.active = false;
+        }
+    }
+
+    private void triggerActivations() {
+        // iterate all activations adding them to their AgendaGroups
+        final Iterator it = this.list.iterator();
+        for ( RuleFlowGroupNode node = (RuleFlowGroupNode) it.next(); node != null; node = (RuleFlowGroupNode) it.next() ) {
+            final Activation activation = node.getActivation();
+            ((BinaryHeapQueueAgendaGroup) activation.getAgendaGroup()).add( activation );
+        }
+    }
+
+    public void clear() {
+        this.list.clear();
+    }
+
+    public int size() {
+        return this.list.size();
+    }
+
+    public void addActivation(final Activation activation) {
+        final RuleFlowGroupNode node = new RuleFlowGroupNode( activation,
+                                                              this );
+        activation.setRuleFlowGroupNode( node );
+        this.list.add( node );
+
+        if ( this.active ) {
+            ((InternalAgendaGroup) activation.getAgendaGroup()).add( activation );
+        }
+    }
+
+    public void removeActivation(final Activation activation) {
+        final RuleFlowGroupNode node = activation.getRuleFlowGroupNode();
+        this.list.remove( node );
+        activation.setActivationGroupNode( null );
+        if ( this.active && this.autoDeactivate ) {
+            if ( this.list.isEmpty() ) {
+                // deactivate callback
+                WorkingMemoryAction action = new DeactivateCallback( this );
+                this.workingMemory.queueWorkingMemoryAction( action );
+            }
+        }
+    }
+    
+    public void addRuleFlowGroupListener(RuleFlowGroupListener listener) {
+        if (listeners == null) {
+            listeners = new ArrayList<RuleFlowGroupListener>();
+        }
+        listeners.add(listener);
+    }
+
+    public void removeRuleFlowGroupListener(RuleFlowGroupListener listener) {
+        if (listeners == null) {
+            listeners.remove(listener);
+        }
+    }
+    
+    public void notifyRuleFlowGroupListeners() {
+        if (listeners != null) {
+            for (java.util.Iterator<RuleFlowGroupListener> iterator = listeners.iterator(); iterator.hasNext(); ) {
+                iterator.next().ruleFlowGroupDeactivated();
+            }
+        }
+    }
+
+    public boolean isEmpty() {
+        return this.list.isEmpty();
+    }
+
+    public java.util.Iterator iterator() {
+        return this.list.javaUtilIterator();
+    }
+
+    public String toString() {
+        return "RuleFlowGroup '" + this.name + "'";
+    }
+
+    public boolean equal(final Object object) {
+        if ( (object == null) || !(object instanceof RuleFlowGroupImpl) ) {
+            return false;
+        }
+
+        if ( ((RuleFlowGroupImpl) object).name.equals( this.name ) ) {
+            return true;
+        }
+
+        return false;
+    }
+
+    public int hashCode() {
+        return this.name.hashCode();
+    }
+
+    public static class DeactivateCallback implements WorkingMemoryAction {
+        private static final long serialVersionUID = 400L;
+        private final InternalRuleFlowGroup ruleFlowGroup;
+
+        public DeactivateCallback(InternalRuleFlowGroup ruleFlowGroup) {
+            this.ruleFlowGroup = ruleFlowGroup;
+        }
+
+        public void execute(InternalWorkingMemory workingMemory) {
+            // check whether ruleflow group is still empty first
+            if (this.ruleFlowGroup.isEmpty()) {
+                // deactivate ruleflow group
+                this.ruleFlowGroup.setActive(false);
+            }
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/RuleFlowGroupListener.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/RuleFlowGroupListener.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/RuleFlowGroupListener.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,7 @@
+package org.drools.common;
+
+public interface RuleFlowGroupListener {
+
+    void ruleFlowGroupDeactivated();
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/RuleFlowGroupNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/RuleFlowGroupNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/RuleFlowGroupNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,44 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.Activation;
+import org.drools.util.AbstractBaseLinkedListNode;
+
+public class RuleFlowGroupNode extends AbstractBaseLinkedListNode {
+
+    private static final long     serialVersionUID = 400L;
+
+    private Activation            activation;
+    private InternalRuleFlowGroup ruleFlowGroup;
+
+    public RuleFlowGroupNode(final Activation activation,
+                             final InternalRuleFlowGroup ruleFlowGroup) {
+        super();
+        this.activation = activation;
+        this.ruleFlowGroup = ruleFlowGroup;
+    }
+
+    public Activation getActivation() {
+        return this.activation;
+    }
+
+    public InternalRuleFlowGroup getRuleFlowGroup() {
+        return this.ruleFlowGroup;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ScheduledAgendaItem.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ScheduledAgendaItem.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/ScheduledAgendaItem.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,241 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.TimerTask;
+
+import org.drools.rule.GroupElement;
+import org.drools.rule.Rule;
+import org.drools.spi.Activation;
+import org.drools.spi.AgendaGroup;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
+import org.drools.util.LinkedList;
+import org.drools.util.LinkedListNode;
+
+/**
+ * Item entry in the <code>Agenda</code>.
+ * 
+ * @author <a href="mailto:bob at eng.werken.com">bob mcwhirter </a>
+ */
+public class ScheduledAgendaItem extends TimerTask
+    implements
+    Activation,
+    Serializable,
+    LinkedListNode {
+    // ------------------------------------------------------------
+    // Instance members
+    // ------------------------------------------------------------
+
+    /**
+     * 
+     */
+    private static final long        serialVersionUID = 400L;
+
+    private LinkedListNode           previous;
+
+    private LinkedListNode           next;
+
+    /** The tuple. */
+    private final Tuple              tuple;
+
+    /** The rule. */
+    private final Rule               rule;
+
+    /** The subrule */
+    private final GroupElement       subrule;
+
+    private final InternalAgenda     agenda;
+
+    private final PropagationContext context;
+
+    private final long               activationNumber;
+
+    private LinkedList               justified;
+
+    private boolean                  activated;
+
+    private ActivationGroupNode      activationGroupNode;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    /**
+     * Construct.
+     * 
+     * @param tuple
+     *            The tuple.
+     * @param rule
+     *            The rule.
+     */
+    public ScheduledAgendaItem(final long activationNumber,
+                               final Tuple tuple,
+                               final InternalAgenda agenda,
+                               final PropagationContext context,
+                               final Rule rule,
+                               final GroupElement subrule) {
+        this.tuple = tuple;
+        this.context = context;
+        this.rule = rule;
+        this.subrule = subrule;
+        this.agenda = agenda;
+        this.activationNumber = activationNumber;
+    }
+
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+    public PropagationContext getPropagationContext() {
+        return this.context;
+    }
+    
+    public int getSalience() {
+        throw new UnsupportedOperationException( "salience is now application to scheduled activations" );
+    }
+
+    /**
+     * Retrieve the rule.
+     * 
+     * @return The rule.
+     */
+    public Rule getRule() {
+        return this.rule;
+    }
+
+    /**
+     * Retrieve the tuple.
+     * 
+     * @return The tuple.
+     */
+    public Tuple getTuple() {
+        return this.tuple;
+    }
+
+    /**
+     * Handle the firing of an alarm.
+     */
+    public void run() {
+        this.agenda.fireActivation( this );
+        this.agenda.getWorkingMemory().fireAllRules();
+    }
+
+    public long getActivationNumber() {
+        return this.activationNumber;
+    }
+
+    public LinkedListNode getNext() {
+        return this.next;
+    }
+
+    public void setNext(final LinkedListNode next) {
+        this.next = next;
+    }
+
+    public LinkedListNode getPrevious() {
+        return this.previous;
+    }
+
+    public void setPrevious(final LinkedListNode previous) {
+        this.previous = previous;
+    }
+
+    public void remove() {
+        this.agenda.removeScheduleItem( this );
+    }
+
+    public String toString() {
+        return "[Activation rule=" + this.rule.getName() + ", tuple=" + this.tuple + "]";
+    }
+
+    public void addLogicalDependency(final LogicalDependency node) {
+        if ( this.justified == null ) {
+            this.justified = new LinkedList();
+        }
+
+        this.justified.add( node );
+    }
+
+    public LinkedList getLogicalDependencies() {
+        return this.justified;
+    }
+
+    public boolean isActivated() {
+        return this.activated;
+    }
+
+    public void setActivated(final boolean activated) {
+        this.activated = activated;
+    }
+
+    public ActivationGroupNode getActivationGroupNode() {
+        return this.activationGroupNode;
+    }
+
+    public void setActivationGroupNode(final ActivationGroupNode activationGroupNode) {
+        this.activationGroupNode = activationGroupNode;
+    }
+
+    public RuleFlowGroupNode getRuleFlowGroupNode() {
+        return null;
+    }
+
+    public void setRuleFlowGroupNode(final RuleFlowGroupNode ruleFlowGroupNode) {
+        throw new UnsupportedOperationException( "Scheduled activations cannot be in a Rule Flow Group" );
+    }
+
+    public AgendaGroup getAgendaGroup() {
+        return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    public boolean equals(final Object object) {
+        if ( object == this ) {
+            return true;
+        }
+
+        if ( (object == null) || !(object instanceof AgendaItem) ) {
+            return false;
+        }
+
+        final AgendaItem otherItem = (AgendaItem) object;
+
+        return (this.rule.equals( otherItem.getRule() ) && this.tuple.equals( otherItem.getTuple() ));
+    }
+
+    /**
+     * Return the hashode of the
+     * <code>TupleKey<code> as the hashCode of the AgendaItem
+     * @return
+     */
+    public int hashCode() {
+        return this.tuple.hashCode();
+    }
+
+    public GroupElement getSubRule() {
+        return this.subrule;
+    }
+
+    public void setLogicalDependencies(LinkedList justified) {
+        this.justified = justified;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/Scheduler.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/Scheduler.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/Scheduler.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,82 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Date;
+import java.util.Timer;
+
+/**
+ * Scheduler for rules requiring truth duration.
+ * 
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter </a>
+ */
+final class Scheduler {
+    // ------------------------------------------------------------
+    // Class members
+    // ------------------------------------------------------------
+
+    /** Singleton instance. */
+    private static final Scheduler INSTANCE = new Scheduler();
+
+    // ------------------------------------------------------------
+    // Class methods
+    // ------------------------------------------------------------
+
+    /**
+     * Retrieve the singleton instance.
+     * 
+     * @return The singleton instance.
+     */
+    static Scheduler getInstance() {
+        return Scheduler.INSTANCE;
+    }
+
+    // ------------------------------------------------------------
+    // Instance members
+    // ------------------------------------------------------------
+
+    /** Alarm manager. */
+    private final Timer scheduler;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    /**
+     * Construct.
+     */
+    private Scheduler() {
+        this.scheduler = new Timer( true );
+    }
+
+    /**
+     * Schedule an agenda item.
+     * 
+     * @param item
+     *            The item to schedule.
+     * @param workingMemory
+     *            The working memory session.
+     */
+    void scheduleAgendaItem(final ScheduledAgendaItem item) {
+        final Date now = new Date();
+
+        final Date then = new Date( now.getTime() + item.getRule().getDuration().getDuration( item.getTuple() ) );
+
+        this.scheduler.schedule( item,
+                                 then );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/SequentialAgendaGroupImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/SequentialAgendaGroupImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/SequentialAgendaGroupImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,154 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.conflict.DepthConflictResolver;
+import org.drools.spi.Activation;
+import org.drools.spi.AgendaGroup;
+import org.drools.spi.ConflictResolver;
+import org.drools.util.BinaryHeapQueue;
+import org.drools.util.PrimitiveLongMap;
+import org.drools.util.Queueable;
+
+/**
+ * <code>AgendaGroup</code> implementation that uses a <code>PriorityQueue</code> to prioritise the evaluation of added
+ * <code>ActivationQueue</code>s. The <code>AgendaGroup</code> also maintains a <code>Map</code> of <code>ActivationQueues</code> 
+ * for requested salience values.
+ * 
+ * @see PriorityQueue
+ * @see ActivationQueue
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ *
+ */
+public class SequentialAgendaGroupImpl
+    implements
+    AgendaGroup {
+
+    private static final long     serialVersionUID = 400L;
+
+    private final String          name;
+
+    /** Items in the agenda. */
+    //private final BinaryHeapQueue queue;
+    private PrimitiveLongMap     queue;
+
+    private boolean               active;
+    
+    private long                  index;
+
+    /**
+     * Construct an <code>AgendaGroup</code> with the given name.
+     * 
+     * @param name
+     *      The <AgendaGroup> name.
+     */
+    
+    
+    public SequentialAgendaGroupImpl(final String name, final ConflictResolver conflictResolver) {
+        this.name = name;
+        this.queue = new PrimitiveLongMap();//new BinaryHeapQueue( conflictResolver );
+    }    
+
+    /* (non-Javadoc)
+     * @see org.drools.spi.AgendaGroup#getName()
+     */
+    public String getName() {
+        return this.name;
+    }
+
+    public void clear() {
+        this.queue.clear();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.spi.AgendaGroup#size()
+     */
+    public int size() {
+        return this.queue.size();
+    }
+
+    public void add(final Activation activation) {
+        this.queue.put( activation.getRule().getLoadOrder(), activation );
+        //this.queue.enqueue( (Queueable) activation );
+    }
+
+    public Activation getNext() {
+        index = this.queue.getNext( index );
+        if ( index == -1 ) {
+            return null;
+        }
+        return ( Activation ) this.queue.get( index );
+//        
+//        if ( index > this.queue.size() ) {
+//            return null;
+//        } else {
+//            return ( Activation ) this.queue.get( index );
+//        }
+    }
+
+    public boolean isActive() {
+        return this.active;
+    }
+
+    public void setActive(final boolean activate) {
+        this.active = activate;
+    }
+
+    /**
+     * Iterates a PriorityQueue removing empty entries until it finds a populated entry and return true,
+     * otherwise it returns false;
+     * 
+     * @param priorityQueue
+     * @return
+     */
+    public boolean isEmpty() {
+        return this.queue.isEmpty();
+    }
+
+    public Activation[] getActivations() {
+        return null;
+        //this.queue.
+        //return (Activation[]) this.queue.toArray( new AgendaItem[this.queue.size()] );
+    }
+
+    public Queueable[] getQueueable() {
+        return null;
+        //return this.queue.getQueueable();
+    }
+
+    public String toString() {
+        return "AgendaGroup '" + this.name + "'";
+    }
+
+    public boolean equal(final Object object) {
+        if ( (object == null) || !(object instanceof SequentialAgendaGroupImpl) ) {
+            return false;
+        }
+
+        if ( ((SequentialAgendaGroupImpl) object).name.equals( this.name ) ) {
+            return true;
+        }
+
+        return false;
+    }
+
+    public int hashCode() {
+        return this.name.hashCode();
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/SingleBetaConstraints.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/SingleBetaConstraints.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/SingleBetaConstraints.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,215 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.drools.RuleBaseConfiguration;
+import org.drools.base.evaluators.Operator;
+import org.drools.reteoo.BetaMemory;
+import org.drools.reteoo.FactHandleMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.reteoo.TupleMemory;
+import org.drools.rule.ContextEntry;
+import org.drools.rule.VariableConstraint;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.util.FactHashTable;
+import org.drools.util.FactHandleIndexHashTable;
+import org.drools.util.LinkedList;
+import org.drools.util.LinkedListEntry;
+import org.drools.util.TupleHashTable;
+import org.drools.util.TupleIndexHashTable;
+import org.drools.util.AbstractHashTable.FieldIndex;
+
+public class SingleBetaConstraints
+    implements
+    Serializable,
+    BetaConstraints {
+
+    /**
+     * 
+     */
+    private static final long             serialVersionUID = 400L;
+
+    private final BetaNodeFieldConstraint constraint;
+
+    private ContextEntry                  context;
+
+    private boolean                       indexed;
+
+    private RuleBaseConfiguration         conf;
+    
+    public SingleBetaConstraints(final BetaNodeFieldConstraint[] constraint,
+                                 final RuleBaseConfiguration conf) {
+        this( constraint[0],
+              conf,
+              false );
+    }    
+
+    public SingleBetaConstraints(final BetaNodeFieldConstraint constraint,
+                                 final RuleBaseConfiguration conf) {
+        this( constraint,
+              conf,
+              false );
+    }
+
+    public SingleBetaConstraints(final BetaNodeFieldConstraint constraint,
+                                 final RuleBaseConfiguration conf,
+                                 final boolean disableIndex) {
+        this.conf = conf;
+        if ( (disableIndex) || (!conf.isIndexLeftBetaMemory() && !conf.isIndexRightBetaMemory()) ) {
+            this.indexed = false;
+        } else {
+            final int depth = conf.getCompositeKeyDepth();
+            // Determine  if this constraint is indexable
+            this.indexed = depth >= 1 && isIndexable( constraint );
+        }
+
+        this.constraint = constraint;
+        this.context = constraint.getContextEntry();
+    }
+
+    private boolean isIndexable(final BetaNodeFieldConstraint constraint) {
+        if ( constraint instanceof VariableConstraint ) {
+            final VariableConstraint variableConstraint = (VariableConstraint) constraint;
+            return (variableConstraint.getEvaluator().getOperator() == Operator.EQUAL);
+        } else {
+            return false;
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#updateFromTuple(org.drools.reteoo.ReteTuple)
+     */
+    public void updateFromTuple(final InternalWorkingMemory workingMemory,
+                                final ReteTuple tuple) {
+        this.context.updateFromTuple( workingMemory,
+                                      tuple );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#updateFromFactHandle(org.drools.common.InternalFactHandle)
+     */
+    public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
+                                     final InternalFactHandle handle) {
+        this.context.updateFromFactHandle( workingMemory,
+                                           handle );
+    }
+    
+    public void resetTuple() {
+        this.context.resetTuple();
+    }
+    
+    public void resetFactHandle() {
+        this.context.resetFactHandle();
+    }     
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#isAllowedCachedLeft(java.lang.Object)
+     */
+    public boolean isAllowedCachedLeft(final InternalFactHandle handle) {
+        return this.indexed || this.constraint.isAllowedCachedLeft( this.context,
+                                                                    handle );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#isAllowedCachedRight(org.drools.reteoo.ReteTuple)
+     */
+    public boolean isAllowedCachedRight(final ReteTuple tuple) {
+        return this.constraint.isAllowedCachedRight( tuple,
+                                                     this.context );
+    }
+
+    public boolean isIndexed() {
+        return this.indexed;
+    }
+    
+    public int getIndexCount() {
+        return ( this.indexed ? 1 : 0 );
+    }
+
+    public boolean isEmpty() {
+        return false;
+    }
+
+    public BetaMemory createBetaMemory(final RuleBaseConfiguration config) {
+        BetaMemory memory;
+        if ( this.indexed ) {
+            final VariableConstraint variableConstraint = (VariableConstraint) this.constraint;
+            final FieldIndex index = new FieldIndex( variableConstraint.getFieldExtractor(),
+                                                     variableConstraint.getRequiredDeclarations()[0],
+                                                     variableConstraint.getEvaluator() );
+            TupleMemory tupleMemory;
+            if ( this.conf.isIndexLeftBetaMemory() ) {
+                tupleMemory = new TupleIndexHashTable( new FieldIndex[]{index} );
+            } else {
+                tupleMemory = new TupleHashTable();
+            }
+
+            FactHandleMemory factHandleMemory;
+            if ( this.conf.isIndexRightBetaMemory() ) {
+                factHandleMemory = new FactHandleIndexHashTable( new FieldIndex[]{index} );
+            } else {
+                factHandleMemory = new FactHashTable();
+            }
+            memory = new BetaMemory( config.isSequential() ? null : tupleMemory,
+                                     factHandleMemory );
+        } else {
+            memory = new BetaMemory( config.isSequential() ? null : new TupleHashTable(),
+                                     new FactHashTable() );
+        }
+
+        return memory;
+    }
+
+    public int hashCode() {
+        return this.constraint.hashCode();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#getConstraints()
+     */
+    public LinkedList getConstraints() {
+        final LinkedList list = new LinkedList();
+        list.add( new LinkedListEntry( this.constraint ) );
+        return list;
+    }
+
+    /**
+     * Determine if another object is equal to this.
+     * 
+     * @param object
+     *            The object to test.
+     * 
+     * @return <code>true</code> if <code>object</code> is equal to this,
+     *         otherwise <code>false</code>.
+     */
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || getClass() != object.getClass() ) {
+            return false;
+        }
+
+        final SingleBetaConstraints other = (SingleBetaConstraints) object;
+
+        return this.constraint == other.constraint || this.constraint.equals( other );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/SingleThreadedObjectStore.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/SingleThreadedObjectStore.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/SingleThreadedObjectStore.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,184 @@
+/**
+ * 
+ */
+package org.drools.common;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.apache.log4j.Logger;
+import org.drools.ObjectFilter;
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuleBaseConfiguration.AssertBehaviour;
+import org.drools.base.ShadowProxy;
+import org.drools.reteoo.TimeWindowNode;
+import org.drools.util.JavaIteratorAdapter;
+import org.drools.util.ObjectHashMap;
+import org.drools.util.AbstractHashTable.HashTableIterator;
+
+public class  SingleThreadedObjectStore implements Serializable, ObjectStore {
+    /** Object-to-handle mapping. */
+    private ObjectHashMap                          assertMap;
+    private ObjectHashMap                          identityMap;
+    private AssertBehaviour                        behaviour;
+    private Lock                                   lock;
+    
+    public SingleThreadedObjectStore(RuleBaseConfiguration conf, Lock lock) {
+        this.behaviour = conf.getAssertBehaviour();
+        this.lock = lock;
+        
+        this.assertMap = new ObjectHashMap();            
+
+        if ( this.behaviour == AssertBehaviour.IDENTITY ) {
+            this.assertMap.setComparator( new IdentityAssertMapComparator() );
+            this.identityMap = assertMap;
+        } else {
+            this.assertMap.setComparator( new EqualityAssertMapComparator() );
+            this.identityMap = new ObjectHashMap();
+            this.identityMap.setComparator( new IdentityAssertMapComparator() );
+        }            
+    }
+    
+    /* (non-Javadoc)
+     * @see org.drools.common.ObjectStore#size()
+     */
+    public int size() {
+        return this.assertMap.size();
+    }
+    
+    /* (non-Javadoc)
+     * @see org.drools.common.ObjectStore#isEmpty()
+     */
+    public boolean isEmpty() {
+        return this.assertMap != null;
+    }
+    
+    /* (non-Javadoc)
+     * @see org.drools.common.ObjectStore#getObjectForHandle(org.drools.common.InternalFactHandle)
+     */
+    public Object getObjectForHandle(InternalFactHandle handle) {
+        //Logger myLogger = Logger.getLogger(SingleThreadedObjectStore.class.getName());
+        //this.lock = new ReentrantLock();
+    	try {
+        	//myLogger.debug ("Thread "+Thread.currentThread().getId() +": TRYING TO ENTER getObjectForHandle("+handle.getObject().toString()+")");
+            this.lock.lock(); 
+            //myLogger.debug ("Thread "+Thread.currentThread().getId() +": ENTERING getObjectForHandle("+handle.getObject().toString()+")");
+
+            // Make sure the FactHandle is from this WorkingMemory
+            final InternalFactHandle internalHandle = (InternalFactHandle) this.assertMap.get( handle );
+            if ( internalHandle == null ) {
+                return null;
+            }
+
+            Object object = internalHandle.getObject();
+
+            if ( object != null && internalHandle.isShadowFact() ) {
+                object = ((ShadowProxy) object).getShadowedObject();
+            }
+
+            return object;
+        } finally {
+            this.lock.unlock(); 
+            //myLogger.debug ("Thread "+Thread.currentThread().getId() +": LEAVING getObjectForHandle("+handle.getObject().toString()+")");
+        }            
+    }
+            
+    /* (non-Javadoc)
+     * @see org.drools.common.ObjectStore#getHandleForObject(java.lang.Object)
+     */
+    public InternalFactHandle getHandleForObject(Object object){
+        return (InternalFactHandle) this.assertMap.get( object );
+    }
+    
+    /* (non-Javadoc)
+     * @see org.drools.common.ObjectStore#getHandleForObject(java.lang.Object)
+     */
+    public InternalFactHandle getHandleForObjectIdentity(Object object) {
+        return (InternalFactHandle) this.identityMap.get( object );
+    }
+    
+    /* (non-Javadoc)
+     * @see org.drools.common.ObjectStore#updateHandle(org.drools.common.InternalFactHandle, java.lang.Object)
+     */
+    public void updateHandle(InternalFactHandle handle, Object object){
+        this.assertMap.remove( handle );
+        Object oldObject = handle.getObject();
+        if ( oldObject instanceof ShadowProxy ) {
+            ((ShadowProxy) oldObject).setShadowedObject( object );
+        } else {
+            handle.setObject( object );
+        }
+        this.assertMap.put( handle,
+                            handle,
+                            false );
+    }
+    
+    /* (non-Javadoc)
+     * @see org.drools.common.ObjectStore#addHandle(org.drools.common.InternalFactHandle, java.lang.Object)
+     */
+    public void addHandle(InternalFactHandle handle, Object object) {
+        this.assertMap.put( handle,
+                            handle,
+                            false );
+        if ( this.behaviour == AssertBehaviour.EQUALITY ) {
+            this.identityMap.put( handle,
+                                  handle,
+                                  false );
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.ObjectStore#removeHandle(org.drools.common.InternalFactHandle)
+     */
+    public void removeHandle(final InternalFactHandle handle) {
+        this.assertMap.remove( handle );
+        if ( this.behaviour == AssertBehaviour.EQUALITY ) {
+            this.identityMap.remove( handle );
+        }
+    }      
+    
+    /* (non-Javadoc)
+     * @see org.drools.common.ObjectStore#iterateObjects()
+     */
+    public Iterator iterateObjects() {
+        HashTableIterator iterator = new HashTableIterator( this.assertMap );
+        iterator.reset();
+        return new JavaIteratorAdapter( iterator,
+                                        JavaIteratorAdapter.OBJECT );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.ObjectStore#iterateObjects(org.drools.ObjectFilter)
+     */
+    public Iterator iterateObjects(ObjectFilter filter) {
+        HashTableIterator iterator = new HashTableIterator( this.assertMap );
+        iterator.reset();
+        return new JavaIteratorAdapter( iterator,
+                                        JavaIteratorAdapter.OBJECT,
+                                        filter );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.ObjectStore#iterateFactHandles()
+     */
+    public Iterator iterateFactHandles() {
+        HashTableIterator iterator = new HashTableIterator( this.assertMap );
+        iterator.reset();
+        return new JavaIteratorAdapter( iterator,
+                                        JavaIteratorAdapter.FACT_HANDLE );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.ObjectStore#iterateFactHandles(org.drools.ObjectFilter)
+     */
+    public Iterator iterateFactHandles(ObjectFilter filter) {
+        HashTableIterator iterator = new HashTableIterator( this.assertMap );
+        iterator.reset();
+        return new JavaIteratorAdapter( iterator,
+                                        JavaIteratorAdapter.FACT_HANDLE,
+                                        filter );
+    }        
+    
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/TripleBetaConstraints.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/TripleBetaConstraints.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/TripleBetaConstraints.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,333 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.RuleBaseConfiguration;
+import org.drools.base.evaluators.Operator;
+import org.drools.reteoo.BetaMemory;
+import org.drools.reteoo.FactHandleMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.reteoo.TupleMemory;
+import org.drools.rule.ContextEntry;
+import org.drools.rule.VariableConstraint;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.util.FactHashTable;
+import org.drools.util.FactHandleIndexHashTable;
+import org.drools.util.FactList;
+import org.drools.util.LinkedList;
+import org.drools.util.LinkedListEntry;
+import org.drools.util.TupleHashTable;
+import org.drools.util.TupleIndexHashTable;
+import org.drools.util.AbstractHashTable.FieldIndex;
+
+public class TripleBetaConstraints
+    implements
+    Serializable,
+    BetaConstraints {
+
+    /**
+     * 
+     */
+    private static final long             serialVersionUID = 400L;
+
+    private final BetaNodeFieldConstraint constraint0;
+    private final BetaNodeFieldConstraint constraint1;
+    private final BetaNodeFieldConstraint constraint2;
+
+    private final ContextEntry            context0;
+    private final ContextEntry            context1;
+    private final ContextEntry            context2;
+
+    private boolean                       indexed0;
+    private boolean                       indexed1;
+    private boolean                       indexed2;
+
+    public TripleBetaConstraints(final BetaNodeFieldConstraint[] constraints,
+                                 final RuleBaseConfiguration conf) {
+        this( constraints,
+              conf,
+              false );
+    }
+
+    public TripleBetaConstraints(final BetaNodeFieldConstraint[] constraints,
+                                 final RuleBaseConfiguration conf,
+                                 final boolean disableIndexing) {
+        if ( disableIndexing || (!conf.isIndexLeftBetaMemory() && !conf.isIndexRightBetaMemory()) ) {
+            this.indexed0 = false;
+            this.indexed1 = false;
+            this.indexed2 = false;
+        } else {
+            final int depth = conf.getCompositeKeyDepth();
+
+            // Determine  if this constraints are indexable               
+            final boolean i0 = isIndexable( constraints[0] );
+            final boolean i1 = isIndexable( constraints[1] );
+            final boolean i2 = isIndexable( constraints[2] );
+
+            if ( depth >= 1 && i0 ) {
+                this.indexed0 = true;
+            }
+
+            if ( i1 ) {
+                if ( depth >= 1 && !this.indexed0 ) {
+                    this.indexed0 = true;
+                    swap( constraints,
+                          1,
+                          0 );
+                } else if ( depth >= 2 ) {
+                    this.indexed1 = true;
+                }
+            }
+
+            if ( i2 ) {
+                if ( depth >= 1 && !this.indexed0 ) {
+                    this.indexed0 = true;
+                    swap( constraints,
+                          2,
+                          0 );
+                } else if ( depth >= 2 && this.indexed0 && !this.indexed1 ) {
+                    this.indexed1 = true;
+                    swap( constraints,
+                          2,
+                          1 );
+                } else if ( depth >= 3 ) {
+                    this.indexed2 = true;
+                }
+            }
+        }
+        this.constraint0 = constraints[0];
+        this.context0 = this.constraint0.getContextEntry();
+
+        this.constraint1 = constraints[1];
+        this.context1 = this.constraint1.getContextEntry();
+
+        this.constraint2 = constraints[2];
+        this.context2 = this.constraint2.getContextEntry();
+    }
+
+    private void swap(final BetaNodeFieldConstraint[] constraints,
+                      final int p1,
+                      final int p2) {
+        final BetaNodeFieldConstraint temp = constraints[p2];
+        constraints[p2] = constraints[p1];
+        constraints[p1] = temp;
+    }
+
+    private boolean isIndexable(final BetaNodeFieldConstraint constraint) {
+        if ( constraint instanceof VariableConstraint ) {
+            final VariableConstraint variableConstraint = (VariableConstraint) constraint;
+            return (variableConstraint.getEvaluator().getOperator() == Operator.EQUAL);
+        } else {
+            return false;
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#updateFromTuple(org.drools.reteoo.ReteTuple)
+     */
+    public void updateFromTuple(final InternalWorkingMemory workingMemory,
+                                final ReteTuple tuple) {
+        this.context0.updateFromTuple( workingMemory,
+                                       tuple );
+        this.context1.updateFromTuple( workingMemory,
+                                       tuple );
+        this.context2.updateFromTuple( workingMemory,
+                                       tuple );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#updateFromFactHandle(org.drools.common.InternalFactHandle)
+     */
+    public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
+                                     final InternalFactHandle handle) {
+        this.context0.updateFromFactHandle( workingMemory,
+                                            handle );
+        this.context1.updateFromFactHandle( workingMemory,
+                                            handle );
+        this.context2.updateFromFactHandle( workingMemory,
+                                            handle );
+    }
+    
+    public void resetTuple() {
+        this.context0.resetTuple();
+        this.context1.resetTuple();
+        this.context2.resetTuple();
+    }
+    
+    public void resetFactHandle() {
+        this.context0.resetFactHandle();
+        this.context1.resetFactHandle();
+        this.context2.resetFactHandle();
+    }     
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#isAllowedCachedLeft(java.lang.Object)
+     */
+    public boolean isAllowedCachedLeft(final InternalFactHandle handle) {
+        //        return ( this.indexed0 || this.constraint0.isAllowedCachedLeft( context0,
+        //                                                                       object ) ) && this.constraint1.isAllowedCachedLeft( context1,
+        //                                                                                                       object ) && this.constraint2.isAllowedCachedLeft( context2,
+        //                                                                                                                                                         object );
+
+        return (this.indexed0 || this.constraint0.isAllowedCachedLeft( this.context0,
+                                                                       handle )) && (this.indexed1 || this.constraint1.isAllowedCachedLeft( this.context1,
+                                                                                                                                            handle )) && (this.indexed2 || this.constraint2.isAllowedCachedLeft( this.context2,
+                                                                                                                                                                                                                 handle ));
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#isAllowedCachedRight(org.drools.reteoo.ReteTuple)
+     */
+    public boolean isAllowedCachedRight(final ReteTuple tuple) {
+        return this.constraint0.isAllowedCachedRight( tuple,
+                                                      this.context0 ) && this.constraint1.isAllowedCachedRight( tuple,
+                                                                                                                this.context1 ) && this.constraint2.isAllowedCachedRight( tuple,
+                                                                                                                                                                          this.context2 );
+    }
+
+    public boolean isIndexed() {
+        return this.indexed0;
+    }
+
+    public int getIndexCount() {
+        int count = 0;
+        if ( this.indexed0 ) {
+            count++;
+        }
+        if ( this.indexed1 ) {
+            count++;
+        }
+        if ( this.indexed2 ) {
+            count++;
+        }
+        return count;
+    }
+
+    public boolean isEmpty() {
+        return false;
+    }
+
+    public BetaMemory createBetaMemory(final RuleBaseConfiguration conf) {
+
+        BetaMemory memory;
+
+        final List list = new ArrayList( 2 );
+        if ( this.indexed0 ) {
+            final VariableConstraint variableConstraint = (VariableConstraint) this.constraint0;
+            final FieldIndex index = new FieldIndex( variableConstraint.getFieldExtractor(),
+                                                     variableConstraint.getRequiredDeclarations()[0],
+                                                     variableConstraint.getEvaluator() );
+            list.add( index );
+
+        }
+
+        if ( this.indexed1 ) {
+            final VariableConstraint variableConstraint = (VariableConstraint) this.constraint1;
+            final FieldIndex index = new FieldIndex( variableConstraint.getFieldExtractor(),
+                                                     variableConstraint.getRequiredDeclarations()[0],
+                                                     variableConstraint.getEvaluator() );
+            list.add( index );
+        }
+
+        if ( this.indexed2 ) {
+            final VariableConstraint variableConstraint = (VariableConstraint) this.constraint2;
+            final FieldIndex index = new FieldIndex( variableConstraint.getFieldExtractor(),
+                                                     variableConstraint.getRequiredDeclarations()[0],
+                                                     variableConstraint.getEvaluator() );
+            list.add( index );
+        }
+
+        if ( !list.isEmpty() ) {
+            final FieldIndex[] indexes = (FieldIndex[]) list.toArray( new FieldIndex[list.size()] );
+            TupleMemory tupleMemory;
+            if ( conf.isIndexLeftBetaMemory() ) {
+                tupleMemory = new TupleIndexHashTable( indexes );
+            } else {
+                tupleMemory = new TupleHashTable();
+            }
+
+            FactHandleMemory factHandleMemory;
+            if ( conf.isIndexRightBetaMemory() ) {
+                factHandleMemory = new FactHandleIndexHashTable( indexes );
+            } else {
+                factHandleMemory = conf.isSequential() ? (FactHandleMemory) new FactList() : (FactHandleMemory) new FactHashTable();
+            }
+            memory = new BetaMemory( conf.isSequential() ? null : tupleMemory,
+                                     factHandleMemory );
+        } else {
+            memory = new BetaMemory( conf.isSequential() ? null : new TupleHashTable(),
+                                     conf.isSequential() ? (FactHandleMemory) new FactList() : (FactHandleMemory) new FactHashTable() );
+        }
+
+        return memory;
+    }
+
+    public int hashCode() {
+        return this.constraint0.hashCode() ^ this.constraint1.hashCode() ^ this.constraint2.hashCode();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.common.BetaNodeConstraints#getConstraints()
+     */
+    public LinkedList getConstraints() {
+        final LinkedList list = new LinkedList();
+        list.add( new LinkedListEntry( this.constraint0 ) );
+        list.add( new LinkedListEntry( this.constraint1 ) );
+        list.add( new LinkedListEntry( this.constraint2 ) );
+        return list;
+    }
+
+    /**
+     * Determine if another object is equal to this.
+     * 
+     * @param object
+     *            The object to test.
+     * 
+     * @return <code>true</code> if <code>object</code> is equal to this,
+     *         otherwise <code>false</code>.
+     */
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || getClass() != object.getClass() ) {
+            return false;
+        }
+
+        final TripleBetaConstraints other = (TripleBetaConstraints) object;
+
+        if ( this.constraint0 != other.constraint0 && !this.constraint0.equals( other.constraint0 ) ) {
+            return false;
+        }
+
+        if ( this.constraint1 != other.constraint1 && !this.constraint1.equals( other.constraint1 ) ) {
+            return false;
+        }
+
+        if ( this.constraint2 != other.constraint2 && !this.constraint2.equals( other.constraint2 ) ) {
+            return false;
+        }
+
+        return true;
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/TruthMaintenanceSystem.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/TruthMaintenanceSystem.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/TruthMaintenanceSystem.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,211 @@
+package org.drools.common;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.drools.FactException;
+import org.drools.rule.Rule;
+import org.drools.spi.Activation;
+import org.drools.spi.PropagationContext;
+import org.drools.util.ObjectHashMap;
+import org.drools.util.PrimitiveLongMap;
+import org.w3c.dom.views.AbstractView;
+
+/**
+ * The Truth Maintenance System is responsible for tracking two things. Firstly
+ * It maintains a Map to track the classes with the same Equality, using the  
+ * EqualityKey. The EqualityKey has an internal datastructure which references
+ * all the handles which are equal. Secondly It maintains another map tracking
+ * the  justificiations for logically asserted facts.
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ *
+ */
+public class TruthMaintenanceSystem
+    implements
+    Serializable {
+
+    private static final long           serialVersionUID = 400L;
+
+    private final AbstractWorkingMemory workingMemory;
+
+    private final PrimitiveLongMap      justifiedMap;
+
+    private final ObjectHashMap         assertMap;
+
+    public TruthMaintenanceSystem(final AbstractWorkingMemory workingMemory) {
+        this.workingMemory = workingMemory;
+
+        this.justifiedMap = new PrimitiveLongMap( 8,
+                                                  32 );
+        this.assertMap = new ObjectHashMap();
+        this.assertMap.setComparator( EqualityKeyComparator.getInstance() );
+    }
+
+    public PrimitiveLongMap getJustifiedMap() {
+        return this.justifiedMap;
+    }
+
+    public ObjectHashMap getAssertMap() {
+        return this.assertMap;
+    }
+
+    public Object put(final EqualityKey key) {
+        return this.assertMap.put( key,
+                                   key,
+                                   false );
+    }
+
+    public EqualityKey get(final EqualityKey key) {
+        return (EqualityKey) this.assertMap.get( key );
+    }
+
+    public EqualityKey get(final Object object) {
+        return (EqualityKey) this.assertMap.get( object );
+    }
+
+    public EqualityKey remove(final EqualityKey key) {
+        return (EqualityKey) this.assertMap.remove( key );
+    }
+
+    /**
+     * An Activation is no longer true so it no longer justifies  any  of the logical facts
+     * it logically  asserted. It iterates  over the Activation's LinkedList of DependencyNodes
+     * it retrieves the justitication  set for each  DependencyNode's FactHandle and  removes
+     * itself. If the Set is empty it retracts the FactHandle from the WorkingMemory. 
+     * 
+     * @param activation 
+     * @param context
+     * @param rule
+     * @throws FactException
+     */
+    public void removeLogicalDependencies(final Activation activation,
+                                          final PropagationContext context,
+                                          final Rule rule) throws FactException {
+        final org.drools.util.LinkedList list = activation.getLogicalDependencies();
+        if ( list == null || list.isEmpty() ) {
+            return;
+        }
+        for ( LogicalDependency node = (LogicalDependency) list.getFirst(); node != null; node = (LogicalDependency) node.getNext() ) {
+            final InternalFactHandle handle = (InternalFactHandle) node.getFactHandle();
+            final Set set = (Set) this.justifiedMap.get( handle.getId() );
+            if ( set != null ) {
+                set.remove( node );
+                WorkingMemoryAction action = new LogicalRetractCallback( this,
+                                                                         node,
+                                                                         set,
+                                                                         handle,
+                                                                         context );
+                workingMemory.queueWorkingMemoryAction( action );
+            }
+        }
+    }
+
+    public static class LogicalRetractCallback
+        implements
+        WorkingMemoryAction {
+        private final TruthMaintenanceSystem tms;
+        private final LogicalDependency      node;
+        private final Set                    set;
+        private final InternalFactHandle     handle;
+        private final PropagationContext     context;
+
+        public LogicalRetractCallback(TruthMaintenanceSystem tms,
+                                      LogicalDependency node,
+                                      Set set,
+                                      InternalFactHandle handle,
+                                      PropagationContext context) {
+            this.tms = tms;
+            this.node = node;
+            this.set = set;
+            this.handle = handle;
+            this.context = context;
+        }
+
+        public void execute(InternalWorkingMemory workingMemory) {
+
+            if ( set.isEmpty() ) {
+                if ( set.isEmpty() ) {
+                    this.tms.getJustifiedMap().remove( handle.getId() );
+                    // this needs to be scheduled so we don't upset the current
+                    // working memory operation
+                    workingMemory.retract( this.handle,
+                                                 false,
+                                                 true,
+                                                 context.getRuleOrigin(),
+                                                 context.getActivationOrigin() );
+                }
+            }
+        }
+    }
+
+    /**
+     * The FactHandle is being removed from the system so remove any logical dependencies
+     * between the  justified FactHandle and its justifiers. Removes the FactHandle key 
+     * from the justifiedMap. It then iterates over all the LogicalDependency nodes, if any, 
+     * in the returned Set and removes the LogicalDependency node from the LinkedList maintained 
+     * by the Activation.
+     * 
+     * @see LogicalDependency
+     * 
+     * @param handle - The FactHandle to be removed
+     * @throws FactException
+     */
+    public void removeLogicalDependencies(final InternalFactHandle handle) throws FactException {
+        final Set set = (Set) this.justifiedMap.remove( handle.getId() );
+        if ( set != null && !set.isEmpty() ) {
+            for ( final Iterator it = set.iterator(); it.hasNext(); ) {
+                final LogicalDependency node = (LogicalDependency) it.next();
+                node.getJustifier().getLogicalDependencies().remove( node );
+            }
+        }
+    }
+
+    /**
+     * Adds a justification for the FactHandle to the justifiedMap.
+     * 
+     * @param handle
+     * @param activation
+     * @param context
+     * @param rule
+     * @throws FactException
+     */
+    public void addLogicalDependency(final InternalFactHandle handle,
+                                     final Activation activation,
+                                     final PropagationContext context,
+                                     final Rule rule) throws FactException {
+        final LogicalDependency node = new LogicalDependency( activation,
+                                                              handle );
+        activation.getRule().setHasLogicalDependency( true );
+
+        activation.addLogicalDependency( node );
+        Set set = (Set) this.justifiedMap.get( handle.getId() );
+        if ( set == null ) {
+            if ( context.getType() == PropagationContext.MODIFICATION ) {
+                // if this was a  update, chances  are its trying  to retract a logical assertion
+            }
+            set = new HashSet();
+            this.justifiedMap.put( handle.getId(),
+                                   set );
+        }
+        set.add( node );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/TupleStartEqualsConstraint.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/TupleStartEqualsConstraint.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/TupleStartEqualsConstraint.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2006 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.common;
+
+import org.drools.reteoo.ReteTuple;
+import org.drools.rule.ContextEntry;
+import org.drools.rule.Declaration;
+import org.drools.spi.BetaNodeFieldConstraint;
+
+/**
+ * Checks if one tuple is the start subtuple of other tuple.
+ * For instance, if we have two tuples:
+ * 
+ * T1 = [ a, b, c ]
+ * T2 = [ a, b, c, d, e]
+ * 
+ * This constraint will evaluate to true as T1 is the starting subtuple
+ * of T2. On the other hand, if we have:
+ * 
+ * T1 = [ a, c, b ]
+ * T2 = [ a, b, c, d, e ]
+ * 
+ * This constraint will evaluate to false, as T1 is not the starting subtuple
+ * of T2. Besides having the same elements, the order is different.
+ * 
+ * This constraint is used when joining subnetworks back into the main 
+ * network.
+ *
+ * @author etirelli
+ *
+ */
+public class TupleStartEqualsConstraint
+    implements
+    BetaNodeFieldConstraint {
+
+    private static final long                       serialVersionUID = 400L;
+
+    private final Declaration[]                     declarations     = new Declaration[0];
+
+    private static final TupleStartEqualsConstraint INSTANCE         = new TupleStartEqualsConstraint();
+
+    // this is a stateless constraint, so we can make it a singleton
+    private TupleStartEqualsConstraint() {
+    }
+
+    public static TupleStartEqualsConstraint getInstance() {
+        return INSTANCE;
+    }
+
+    public Declaration[] getRequiredDeclarations() {
+        return this.declarations;
+    }
+    
+    public void replaceDeclaration(Declaration oldDecl,
+                                   Declaration newDecl) {
+    }
+
+    public ContextEntry getContextEntry() {
+        return new TupleStartEqualsConstraintContextEntry();
+    }
+
+    public boolean isAllowedCachedLeft(final ContextEntry context,
+                                       final InternalFactHandle handle) {
+        // object MUST be a ReteTuple
+        final ReteTuple tuple = ((ReteTuple) handle.getObject()).getSubTuple( ((TupleStartEqualsConstraintContextEntry) context).compareSize );
+        return ((TupleStartEqualsConstraintContextEntry) context).left.equals( tuple );
+    }
+
+    public boolean isAllowedCachedRight(final ReteTuple tuple,
+                                        final ContextEntry context) {
+        return tuple.equals( ((TupleStartEqualsConstraintContextEntry) context).right.getSubTuple( tuple.size() ) );
+    }
+
+    public String toString() {
+        return "[ TupleStartEqualsConstraint ]";
+    }
+
+    public int hashCode() {
+        return 10;
+    }
+
+    public boolean equals(final Object object) {
+        if ( object instanceof TupleStartEqualsConstraint ) {
+            return true;
+        }
+        return false;
+    }
+    
+    public Object clone() {
+        return INSTANCE; 
+    }
+
+    public static class TupleStartEqualsConstraintContextEntry
+        implements
+        ContextEntry {
+
+        private static final long serialVersionUID = 400L;
+
+        public ReteTuple          left;
+        public ReteTuple          right;
+
+        // the size of the tuple to compare
+        public int                compareSize;
+
+        private ContextEntry      entry;
+
+        public TupleStartEqualsConstraintContextEntry() {
+        }
+
+        public ContextEntry getNext() {
+            return this.entry;
+        }
+
+        public void setNext(final ContextEntry entry) {
+            this.entry = entry;
+        }
+
+        public void updateFromTuple(final InternalWorkingMemory workingMemory,
+                                    final ReteTuple tuple) {
+            this.left = tuple;
+            this.compareSize = tuple.size();
+        }
+
+        public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
+                                         final InternalFactHandle handle) {
+            // if it is not a rete tuple, then there is a bug in the engine...
+            // it MUST be a rete tuple
+            this.right = (ReteTuple) handle.getObject();
+        }
+        
+        public void resetTuple() {
+            this.left = null;
+        }
+        
+        public void resetFactHandle() {
+            this.right = null;
+        }         
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/WorkingMemoryAction.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/WorkingMemoryAction.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/common/WorkingMemoryAction.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,10 @@
+/**
+ * 
+ */
+package org.drools.common;
+
+import java.io.Serializable;
+
+public interface WorkingMemoryAction extends Serializable {
+    public void execute(InternalWorkingMemory workingMemory);
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/AssertObject.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/AssertObject.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/AssertObject.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,43 @@
+/**
+ * 
+ */
+package org.drools.concurrent;
+
+import org.drools.WorkingMemory;
+
+public class AssertObject
+    implements
+    Command,
+    Future {
+    private Object          object;
+    private volatile Object result;
+    private Exception       e;
+
+    public AssertObject(final Object object) {
+        this.object = object;
+    }
+
+    public void execute(final WorkingMemory workingMemory) {
+        try {
+            this.result = workingMemory.insert( this.object );
+        } catch ( Exception e ) {
+            this.e = e;
+        }
+    }
+
+    public Object getObject() {
+        return this.result;
+    }    
+
+    public boolean isDone() {
+        return this.result != null;
+    }
+    
+    public boolean exceptionThrown() {
+        return e != null;
+    }
+    
+    public Exception getException() {
+        return this.e;
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/AssertObjects.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/AssertObjects.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/AssertObjects.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,59 @@
+/**
+ * 
+ */
+package org.drools.concurrent;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.drools.WorkingMemory;
+
+public class AssertObjects
+    implements
+    Command,
+    Future {
+    private Object        object;
+    private volatile List results;
+    private Exception     e;
+
+    public AssertObjects(final Object object) {
+        this.object = object;
+    }
+
+    public void execute(final WorkingMemory workingMemory) {
+        try {
+            if ( this.object instanceof Object[] ) {
+                final Object[] objects = (Object[]) this.object;
+                this.results = new ArrayList( objects.length );
+                for ( int i = 0; i < objects.length; i++ ) {
+                    this.results.add( workingMemory.insert( objects[i] ) );
+                }
+            } else if ( this.object instanceof List ) {
+                final List list = (List) this.object;
+                this.results = new ArrayList( list.size() );
+                for ( final Iterator it = list.iterator(); it.hasNext(); ) {
+                    this.results.add( workingMemory.insert( it.next() ) );
+                }
+            }
+        } catch ( Exception e ) {
+            this.e = e;
+        }        
+    }
+
+    public Object getObject() {
+        return this.results;
+    }
+
+    public boolean isDone() {
+        return this.results != null;
+    }
+    
+    public boolean exceptionThrown() {
+        return e != null;
+    }
+    
+    public Exception getException() {
+        return this.e;
+    }    
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/Command.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/Command.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/Command.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,12 @@
+/**
+ * 
+ */
+package org.drools.concurrent;
+
+import java.io.Serializable;
+
+import org.drools.WorkingMemory;
+
+public interface Command extends Serializable {
+    void execute(WorkingMemory workingMemory);
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/CommandExecutor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/CommandExecutor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/CommandExecutor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,66 @@
+/**
+ * 
+ */
+package org.drools.concurrent;
+
+import java.io.Serializable;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import org.drools.WorkingMemory;
+
+/**
+ * The CommandExecutor is a Producer/Consumer style classes that provides a queue of Commands
+ * in a LinkedBlockingQueue. This the run() method loops for continously until shutdown() is 
+ * called.
+ *
+ */
+public class CommandExecutor implements Runnable, Serializable {
+
+    private static final long serialVersionUID = 5924295088331461167L;
+    
+    private WorkingMemory workingMemory;
+    private BlockingQueue queue;
+    
+    private volatile boolean run;
+    
+    
+    public CommandExecutor(WorkingMemory workingMemory) {
+        this.workingMemory = workingMemory;            
+        this.queue = new LinkedBlockingQueue();
+    }        
+    
+    /**
+     * Allows the looping run() method to execute. 
+     *
+     */
+    public void shutdown() {
+        this.run = false;
+    }        
+    
+    /**
+     * Submit a Command for execution
+     * 
+     * @param command
+     * 
+     * @return
+     *     return the Future
+     */
+    public Future submit(Command command) {
+        this.queue.offer( command );
+        // we know our commands also implement Future
+        return (Future) command;
+    }
+
+    public void run() {
+        this.run = true;
+        while (this.run) {
+            try {
+                Command executor = ( Command ) this.queue.take();
+                executor.execute( this.workingMemory );
+            } catch(InterruptedException e) {
+                return;
+            }
+        }
+    }        
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/DefaultExecutorService.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/DefaultExecutorService.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/DefaultExecutorService.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,40 @@
+/**
+ * 
+ */
+package org.drools.concurrent;
+
+
+public class DefaultExecutorService implements ExecutorService {   
+
+    private static final long serialVersionUID = 7860812696865293690L;
+    private Thread thread;
+    private CommandExecutor executor;
+    private boolean running;
+    
+    public DefaultExecutorService() {
+        
+    }
+    
+    public void setCommandExecutor(CommandExecutor executor) {
+        this.executor = executor;
+    }
+    
+    public void startUp() {
+        this.thread = new Thread( executor );
+        this.thread.start();
+        this.running = true;
+    }
+    
+    public void shutDown() {
+        this.executor.shutdown();
+        this.running = false;
+        this.thread = null;
+    }             
+    
+    public Future submit(Command command) {
+        if (!this.running) {
+            startUp();
+        }
+        return this.executor.submit( command );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/ExecutorService.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/ExecutorService.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/ExecutorService.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,41 @@
+/**
+ * 
+ */
+package org.drools.concurrent;
+
+import java.io.Serializable;
+
+
+/**
+ * This class instance is configed by the RuleBaseConfiguration and is responsible for thread management
+ * of the async services.
+ *
+ */
+public interface ExecutorService extends Serializable {
+    
+    /**
+     * The CommandExecutor is a producer/consumer style class that handles the queue and execution
+     * of the async actions
+     * @param executor
+     */
+    public void setCommandExecutor(CommandExecutor executor);
+    
+    /**
+     * Submit a command for execution, adds it ot the commandExecutor's queue
+     * @param command
+     * @return
+     */
+    Future submit(Command command);
+    
+    /**
+     * Shutdown this ExecutorService
+     *
+     */
+    void shutDown();
+    
+    /**
+     * Startup this ExecutorService, typically called on first submit for lazy startup.
+     *
+     */
+    void startUp();
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/FireAllRules.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/FireAllRules.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/FireAllRules.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,45 @@
+/**
+ * 
+ */
+package org.drools.concurrent;
+
+import org.drools.WorkingMemory;
+import org.drools.spi.AgendaFilter;
+
+public class FireAllRules
+    implements
+    Command,
+    Future {
+    private AgendaFilter     agendaFilter;
+    private volatile boolean done;
+    private Exception     e;
+
+    public FireAllRules(final AgendaFilter agendaFilter) {
+        this.agendaFilter = agendaFilter;
+    }
+
+    public void execute(final WorkingMemory workingMemory) {
+        try {
+            workingMemory.fireAllRules( this.agendaFilter );
+        } catch ( Exception e ) {
+            this.e = e;
+        }
+        this.done = true;
+    }
+
+    public Object getObject() {
+        return null;
+    }
+
+    public boolean isDone() {
+        return this.done;
+    }
+    
+    public boolean exceptionThrown() {
+        return e != null;
+    }
+    
+    public Exception getException() {
+        return this.e;
+    }      
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/Future.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/Future.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/Future.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,12 @@
+package org.drools.concurrent;
+
+import java.io.Serializable;
+
+public interface Future extends Serializable  {
+    boolean isDone();
+    
+    Object getObject();
+    
+    boolean exceptionThrown();
+    Exception getException();
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/InternalFuture.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/InternalFuture.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/InternalFuture.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,6 @@
+package org.drools.concurrent;
+
+public interface InternalFuture extends Future {
+    void setObject(Object object);
+    Command getCommand();
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/RetractObject.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/RetractObject.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/RetractObject.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,42 @@
+/**
+ * 
+ */
+package org.drools.concurrent;
+
+import org.drools.FactHandle;
+import org.drools.WorkingMemory;
+
+public class RetractObject
+    implements
+    Command,
+    Future {
+    private FactHandle       factHandle;
+    private volatile boolean done;
+    private Exception     e;
+
+    public RetractObject(final FactHandle factHandle) {
+        this.factHandle = factHandle;
+    }
+
+    public void execute(final WorkingMemory workingMemory) {
+        workingMemory.retract( this.factHandle );
+        this.done = true;
+
+    }
+
+    public Object getObject() {
+        return null;
+    }
+
+    public boolean isDone() {
+        return this.done;
+    }
+    
+    public boolean exceptionThrown() {
+        return e != null;
+    }
+    
+    public Exception getException() {
+        return this.e;
+    }    
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/UpdateObject.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/UpdateObject.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/concurrent/UpdateObject.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,45 @@
+/**
+ * 
+ */
+package org.drools.concurrent;
+
+import org.drools.FactHandle;
+import org.drools.WorkingMemory;
+
+public class UpdateObject
+    implements
+    Command,
+    Future {
+    private FactHandle       factHandle;
+    private Object           object;
+    private volatile boolean done;
+    private Exception     e;
+
+    public UpdateObject(final FactHandle factHandle,
+                        final Object object) {
+        this.factHandle = factHandle;
+        this.object = object;
+    }
+
+    public void execute(final WorkingMemory workingMemory) {
+        workingMemory.update( this.factHandle,
+                                    this.object );
+        this.done = true;
+    }
+
+    public Object getObject() {
+        return null;
+    }
+
+    public boolean isDone() {
+        return this.done == true;
+    }
+    
+    public boolean exceptionThrown() {
+        return e != null;
+    }
+    
+    public Exception getException() {
+        return this.e;
+    }    
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/AbstractConflictResolver.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/AbstractConflictResolver.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/AbstractConflictResolver.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,41 @@
+package org.drools.conflict;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.Activation;
+import org.drools.spi.ConflictResolver;
+
+/**
+ * Convenience base class for <code>ConflictResolver</code>s.
+ * 
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris </a>
+ * 
+ * @version $Id: AbstractConflictResolver.java,v 1.1 2004/10/06 13:38:05
+ *          mproctor Exp $
+ */
+public abstract class AbstractConflictResolver
+    implements
+    ConflictResolver {
+    /**
+     * @see ConflictResolver
+     */
+    public final int compare(final Object existing,
+                             final Object adding) {
+        return compare( (Activation) existing,
+                        (Activation) adding );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/ComplexityConflictResolver.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/ComplexityConflictResolver.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/ComplexityConflictResolver.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,80 @@
+package org.drools.conflict;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.Activation;
+import org.drools.spi.ConflictResolver;
+
+/**
+ * <code>ConflictResolver</code> that uses the numConditions of rules to
+ * resolve conflict.
+ * 
+ * @see #getInstance
+ * @see org.drools.rule.Rule#getConditionSize
+ * 
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter </a>
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris </a>
+ * 
+ * @version $Id: ComplexityConflictResolver.java,v 1.9 2004/11/13 01:43:07 simon
+ *          Exp $
+ */
+public class ComplexityConflictResolver extends AbstractConflictResolver {
+    // ----------------------------------------------------------------------
+    // Class members
+    // ----------------------------------------------------------------------
+
+    /**
+     * 
+     */
+    private static final long                       serialVersionUID = 400L;
+    /** Singleton instance. */
+    private static final ComplexityConflictResolver INSTANCE         = new ComplexityConflictResolver();
+
+    // ----------------------------------------------------------------------
+    // Class methods
+    // ----------------------------------------------------------------------
+
+    /**
+     * Retrieve the singleton instance.
+     * 
+     * @return The singleton instance.
+     */
+    public static ConflictResolver getInstance() {
+        return ComplexityConflictResolver.INSTANCE;
+    }
+
+    // ----------------------------------------------------------------------
+    // Constructors
+    // ----------------------------------------------------------------------
+
+    /**
+     * Construct.
+     */
+    public ComplexityConflictResolver() {
+        // intentionally left blank
+    }
+
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+    /**
+     * @see ConflictResolver
+     */
+    public int compare(final Activation lhs,
+                       final Activation rhs) {
+        return rhs.getRule().getSpecifity() - lhs.getRule().getSpecifity();
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/CompositeConflictResolver.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/CompositeConflictResolver.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/CompositeConflictResolver.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,62 @@
+package org.drools.conflict;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.Activation;
+import org.drools.spi.ConflictResolver;
+
+/**
+ * Strategy for resolving conflicts amongst multiple rules.
+ * 
+ * <p>
+ * Since a fact or set of facts may activate multiple rules, a
+ * <code>ConflictResolutionStrategy</code> is used to provide priority
+ * ordering of conflicting rules.
+ * </p>
+ * 
+ * @see Activation
+ * @see org.drools.spi.Tuple
+ * @see org.drools.rule.Rule
+ * 
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris </a>
+ */
+public class CompositeConflictResolver extends AbstractConflictResolver {
+    /**
+     * 
+     */
+    private static final long        serialVersionUID = 400L;
+    private final ConflictResolver[] components;
+
+    public CompositeConflictResolver(final ConflictResolver[] components) {
+        this.components = components;
+    }
+
+    /**
+     * @see AbstractConflictResolver
+     */
+    public final int compare(final Activation lhs,
+                             final Activation rhs) {
+        int result = 0;
+
+        for ( int i = 0; result == 0 && i < this.components.length; ++i ) {
+            result = this.components[i].compare( lhs,
+                                                 rhs );
+        }
+
+        return result;
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/DepthConflictResolver.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/DepthConflictResolver.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/DepthConflictResolver.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,58 @@
+package org.drools.conflict;
+
+import org.drools.spi.Activation;
+import org.drools.spi.ConflictResolver;
+
+public class DepthConflictResolver
+    implements
+    ConflictResolver {
+    /**
+     * 
+     */
+    private static final long                 serialVersionUID = 400L;
+    public static final DepthConflictResolver INSTANCE         = new DepthConflictResolver();
+
+    public static ConflictResolver getInstance() {
+        return DepthConflictResolver.INSTANCE;
+    }
+
+    /**
+     * @see ConflictResolver
+     */
+    public final int compare(final Object existing,
+                             final Object adding) {
+        return compare( (Activation) existing,
+                        (Activation) adding );
+    }
+
+    public int compare(final Activation lhs,
+                       final Activation rhs) {
+        final int s1 = lhs.getSalience();
+        final int s2 = rhs.getSalience();
+
+        if ( s1 > s2 ) {                        
+            return -1;
+        } else if ( s1 < s2 ) {
+            return 1;
+        }
+
+        final long p1 = lhs.getPropagationContext().getPropagationNumber();
+        final long p2 = rhs.getPropagationContext().getPropagationNumber();
+        if ( p1 != p2 ) {
+            return (int) (p2 - p1);
+        }
+
+        final long r1 = lhs.getTuple().getRecency();
+        final long r2 = rhs.getTuple().getRecency();
+
+        if ( r1 != r2 ) {
+            return (int) (r2 - r1);
+        }
+
+        final long l1 = lhs.getRule().getLoadOrder();
+        final long l2 = rhs.getRule().getLoadOrder();
+
+        return (int) (l2 - l1);
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/FifoConflictResolver.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/FifoConflictResolver.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/FifoConflictResolver.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,78 @@
+package org.drools.conflict;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.Activation;
+import org.drools.spi.ConflictResolver;
+
+/**
+ * <code>ConflictResolver</code> that orders rules on a First-In-First-Out
+ * basis.
+ * 
+ * @see #getInstance
+ * 
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris </a>
+ * 
+ * @version $Id: RandomConflictResolver.java,v 1.1 2004/06/25 01:55:16 mproctor
+ *          Exp $
+ */
+public class FifoConflictResolver extends AbstractConflictResolver {
+    // ----------------------------------------------------------------------
+    // Class members
+    // ----------------------------------------------------------------------
+
+    /**
+     * 
+     */
+    private static final long                 serialVersionUID = 400L;
+    /** Singleton instance. */
+    private static final FifoConflictResolver INSTANCE         = new FifoConflictResolver();
+
+    // ----------------------------------------------------------------------
+    // Class methods
+    // ----------------------------------------------------------------------
+
+    /**
+     * Retrieve the singleton instance.
+     * 
+     * @return The singleton instance.
+     */
+    public static ConflictResolver getInstance() {
+        return FifoConflictResolver.INSTANCE;
+    }
+
+    // ----------------------------------------------------------------------
+    // Constructors
+    // ----------------------------------------------------------------------
+
+    /**
+     * Construct.
+     */
+    public FifoConflictResolver() {
+        // intentionally left blank
+    }
+
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+    /**
+     * @see ConflictResolver
+     */
+    public int compare(final Activation lhs,
+                       final Activation rhs) {
+        return (int) (lhs.getActivationNumber() - rhs.getActivationNumber());
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/LifoConflictResolver.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/LifoConflictResolver.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/LifoConflictResolver.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,78 @@
+package org.drools.conflict;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.Activation;
+import org.drools.spi.ConflictResolver;
+
+/**
+ * <code>ConflictResolver</code> that orders rules on a Last-In-First-Out
+ * basis.
+ * 
+ * @see #getInstance
+ * 
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris </a>
+ * 
+ * @version $Id: RandomConflictResolver.java,v 1.1 2004/06/25 01:55:16 mproctor
+ *          Exp $
+ */
+public class LifoConflictResolver extends AbstractConflictResolver {
+    // ----------------------------------------------------------------------
+    // Class members
+    // ----------------------------------------------------------------------
+
+    /**
+     * 
+     */
+    private static final long                 serialVersionUID = 400L;
+    /** Singleton instance. */
+    private static final LifoConflictResolver INSTANCE         = new LifoConflictResolver();
+
+    // ----------------------------------------------------------------------
+    // Class methods
+    // ----------------------------------------------------------------------
+
+    /**
+     * Retrieve the singleton instance.
+     * 
+     * @return The singleton instance.
+     */
+    public static ConflictResolver getInstance() {
+        return LifoConflictResolver.INSTANCE;
+    }
+
+    // ----------------------------------------------------------------------
+    // Constructors
+    // ----------------------------------------------------------------------
+
+    /**
+     * Construct.
+     */
+    public LifoConflictResolver() {
+        // intentionally left blank
+    }
+
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+    /**
+     * @see ConflictResolver
+     */
+    public int compare(final Activation lhs,
+                       final Activation rhs) {
+        return (int) (rhs.getActivationNumber() - lhs.getActivationNumber());
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/LoadOrderConflictResolver.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/LoadOrderConflictResolver.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/LoadOrderConflictResolver.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,80 @@
+package org.drools.conflict;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.Activation;
+import org.drools.spi.ConflictResolver;
+
+/**
+ * <code>ConflictResolver</code> that uses the loadOrder of rules to resolve
+ * conflict.
+ * 
+ * @see #getInstance
+ * @see org.drools.rule.Rule#getLoadOrder
+ * 
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter </a>
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris </a>
+ * 
+ * @version $Id: LoadOrderConflictResolver.java,v 1.1 2004/06/25 01:55:16
+ *          mproctor Exp $
+ */
+public class LoadOrderConflictResolver extends AbstractConflictResolver {
+    // ----------------------------------------------------------------------
+    // Class members
+    // ----------------------------------------------------------------------
+
+    /**
+     * 
+     */
+    private static final long                      serialVersionUID = 400L;
+    /** Singleton instance. */
+    private static final LoadOrderConflictResolver INSTANCE         = new LoadOrderConflictResolver();
+
+    // ----------------------------------------------------------------------
+    // Class methods
+    // ----------------------------------------------------------------------
+
+    /**
+     * Retrieve the singleton instance.
+     * 
+     * @return The singleton instance.
+     */
+    public static ConflictResolver getInstance() {
+        return LoadOrderConflictResolver.INSTANCE;
+    }
+
+    // ----------------------------------------------------------------------
+    // Constructors
+    // ----------------------------------------------------------------------
+
+    /**
+     * Construct.
+     */
+    public LoadOrderConflictResolver() {
+        // intentionally left blank
+    }
+
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+    /**
+     * @see ConflictResolver
+     */
+    public int compare(final Activation lhs,
+                       final Activation rhs) {
+        return (int) (lhs.getRule().getLoadOrder() - rhs.getRule().getLoadOrder());
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/RandomConflictResolver.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/RandomConflictResolver.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/RandomConflictResolver.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,80 @@
+package org.drools.conflict;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.Activation;
+import org.drools.spi.ConflictResolver;
+
+/**
+ * <code>ConflictResolver</code> that uses the semi-random order of rules to
+ * resolve conflict.
+ * 
+ * @see #getInstance
+ * @see System#identityHashCode(Object)
+ * 
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter </a>
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris </a>
+ * 
+ * @version $Id: RandomConflictResolver.java,v 1.1 2004/06/25 01:55:16 mproctor
+ *          Exp $
+ */
+public class RandomConflictResolver extends AbstractConflictResolver {
+    // ----------------------------------------------------------------------
+    // Class members
+    // ----------------------------------------------------------------------
+
+    /**
+     * 
+     */
+    private static final long                   serialVersionUID = 400L;
+    /** Singleton instance. */
+    private static final RandomConflictResolver INSTANCE         = new RandomConflictResolver();
+
+    // ----------------------------------------------------------------------
+    // Class methods
+    // ----------------------------------------------------------------------
+
+    /**
+     * Retrieve the singleton instance.
+     * 
+     * @return The singleton instance.
+     */
+    public static ConflictResolver getInstance() {
+        return RandomConflictResolver.INSTANCE;
+    }
+
+    // ----------------------------------------------------------------------
+    // Constructors
+    // ----------------------------------------------------------------------
+
+    /**
+     * Construct.
+     */
+    public RandomConflictResolver() {
+        // intentionally left blank
+    }
+
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+    /**
+     * @see ConflictResolver
+     */
+    public int compare(final Activation lhs,
+                       final Activation rhs) {
+        return System.identityHashCode( lhs ) - System.identityHashCode( rhs );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/RecencyConflictResolver.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/RecencyConflictResolver.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/RecencyConflictResolver.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,136 @@
+package org.drools.conflict;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.common.InternalFactHandle;
+import org.drools.spi.Activation;
+import org.drools.spi.ConflictResolver;
+
+/**
+ * <code>ConflictResolver</code> that uses the mostRecentFactTimeStamp of
+ * rules to resolve conflict.
+ * 
+ * @see #getInstance
+ * @see org.drools.spi.Tuple#getMostRecentFactTimeStamp
+ * 
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter </a>
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris </a>
+ */
+public class RecencyConflictResolver extends AbstractConflictResolver {
+    // ----------------------------------------------------------------------
+    // Class members
+    // ----------------------------------------------------------------------
+
+    /**
+     * 
+     */
+    private static final long                    serialVersionUID = 400L;
+    /** Singleton instance. */
+    private static final RecencyConflictResolver INSTANCE         = new RecencyConflictResolver();
+
+    // ----------------------------------------------------------------------
+    // Class methods
+    // ----------------------------------------------------------------------
+
+    /**
+     * Retrieve the singleton instance.
+     * 
+     * @return The singleton instance.
+     */
+    public static ConflictResolver getInstance() {
+        return RecencyConflictResolver.INSTANCE;
+    }
+
+    // ----------------------------------------------------------------------
+    // Constructors
+    // ----------------------------------------------------------------------
+
+    /**
+     * Construct.
+     */
+    public RecencyConflictResolver() {
+        // intentionally left blank
+    }
+
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+    /**
+     * @see ConflictResolver
+     */
+    public int compare(final Activation lhs,
+                       final Activation rhs) {
+        final InternalFactHandle[] lFacts = lhs.getTuple().getFactHandles();
+        final InternalFactHandle[] rFacts = rhs.getTuple().getFactHandles();
+
+        InternalFactHandle leftMostRecent = getMostRecentFact( lFacts );
+        InternalFactHandle rightMostRecent = getMostRecentFact( rFacts );
+
+        final int lastIndex = (lFacts.length < rFacts.length) ? lFacts.length : rFacts.length;
+
+        if ( leftMostRecent.getRecency() == rightMostRecent.getRecency() && lastIndex > 1 ) {
+
+            for ( int i = 0; i < lastIndex; i++ ) {
+                leftMostRecent = getMostRecentFact( lFacts,
+                                                    leftMostRecent );
+                rightMostRecent = getMostRecentFact( rFacts,
+                                                     rightMostRecent );
+                if ( leftMostRecent == null || rightMostRecent == null ) {
+                    if ( leftMostRecent == null && rightMostRecent != null ) {
+                        return (int) rightMostRecent.getRecency();
+                    }
+                } else if ( leftMostRecent.getRecency() != rightMostRecent.getRecency() ) {
+                    return (int) (rightMostRecent.getRecency() - leftMostRecent.getRecency());
+                }
+            }
+        } else {
+            return (int) (rightMostRecent.getRecency() - leftMostRecent.getRecency());
+        }
+
+        return rFacts.length - lFacts.length;
+    }
+
+    private InternalFactHandle getMostRecentFact(final InternalFactHandle[] handles) {
+        InternalFactHandle mostRecent = handles[0];
+        for ( int i = 1; i < handles.length; i++ ) {
+            final InternalFactHandle eachHandle = handles[i];
+
+            if ( eachHandle.getRecency() > mostRecent.getRecency() ) {
+                mostRecent = eachHandle;
+            }
+        }
+        return mostRecent;
+    }
+
+    private InternalFactHandle getMostRecentFact(final InternalFactHandle[] handles,
+                                                 final InternalFactHandle handle) {
+        InternalFactHandle mostRecent = null;
+
+        for ( int i = 0; i < handles.length; i++ ) {
+            final InternalFactHandle eachHandle = handles[i];
+
+            if ( mostRecent == null && eachHandle.getRecency() < handle.getRecency() ) {
+                mostRecent = eachHandle;
+            }
+
+            if ( mostRecent != null && eachHandle.getRecency() > mostRecent.getRecency() && eachHandle.getRecency() < handle.getRecency() ) {
+                mostRecent = eachHandle;
+            }
+        }
+        return mostRecent;
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/SalienceConflictResolver.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/SalienceConflictResolver.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/SalienceConflictResolver.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,89 @@
+package org.drools.conflict;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.Activation;
+import org.drools.spi.ConflictResolver;
+
+/**
+ * <code>ConflictResolver</code> that uses the salience of rules to resolve
+ * conflict.
+ * 
+ * @see #getInstance
+ * @see org.drools.rule.Rule#getSalience
+ * 
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter </a>
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris </a>
+ * 
+ * @version $Id: SalienceConflictResolver.java,v 1.3 2004/06/25 02:46:39
+ *          mproctor Exp $
+ */
+public class SalienceConflictResolver extends AbstractConflictResolver {
+    // ----------------------------------------------------------------------
+    // Class members
+    // ----------------------------------------------------------------------
+
+    /**
+     * 
+     */
+    private static final long                     serialVersionUID = 400L;
+    /** Singleton instance. */
+    private static final SalienceConflictResolver INSTANCE         = new SalienceConflictResolver();
+
+    // ----------------------------------------------------------------------
+    // Class methods
+    // ----------------------------------------------------------------------
+
+    /**
+     * Retrieve the singleton instance.
+     * 
+     * @return The singleton instance.
+     */
+    public static ConflictResolver getInstance() {
+        return SalienceConflictResolver.INSTANCE;
+    }
+
+    // ----------------------------------------------------------------------
+    // Constructors
+    // ----------------------------------------------------------------------
+
+    /**
+     * Construct.
+     */
+    public SalienceConflictResolver() {
+        // intentionally left blank
+    }
+
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+    /**
+     * @see ConflictResolver
+     */
+    public int compare(final Activation lhs,
+                       final Activation rhs) {
+        final int s1 = lhs.getSalience();
+        final int s2 = rhs.getSalience();
+
+        if ( s1 > s2 ) {                        
+            return -1;
+        } else if ( s1 < s2 ) {
+            return 1;
+        } else {
+            return 0;
+        }
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/SimplicityConflictResolver.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/SimplicityConflictResolver.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/SimplicityConflictResolver.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,80 @@
+package org.drools.conflict;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.Activation;
+import org.drools.spi.ConflictResolver;
+
+/**
+ * <code>ConflictResolver</code> that uses the numConditions of rules to
+ * resolve conflict.
+ * 
+ * @see #getInstance
+ * @see org.drools.rule.Rule#getConditionSize
+ * 
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter </a>
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris </a>
+ * 
+ * @version $Id: SimplicityConflictResolver.java,v 1.9 2004/11/13 01:43:07 simon
+ *          Exp $
+ */
+public class SimplicityConflictResolver extends AbstractConflictResolver {
+    // ----------------------------------------------------------------------
+    // Class members
+    // ----------------------------------------------------------------------
+
+    /**
+     * 
+     */
+    private static final long                       serialVersionUID = 400L;
+    /** Singleton instance. */
+    private static final SimplicityConflictResolver INSTANCE         = new SimplicityConflictResolver();
+
+    // ----------------------------------------------------------------------
+    // Class methods
+    // ----------------------------------------------------------------------
+
+    /**
+     * Retrieve the singleton instance.
+     * 
+     * @return The singleton instance.
+     */
+    public static ConflictResolver getInstance() {
+        return SimplicityConflictResolver.INSTANCE;
+    }
+
+    // ----------------------------------------------------------------------
+    // Constructors
+    // ----------------------------------------------------------------------
+
+    /**
+     * Construct.
+     */
+    public SimplicityConflictResolver() {
+        // intentionally left blank
+    }
+
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+    /**
+     * @see ConflictResolver
+     */
+    public int compare(final Activation lhs,
+                       final Activation rhs) {
+        return lhs.getRule().getSpecifity() - rhs.getRule().getSpecifity();
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/TotalRecencyConflictResolver.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/TotalRecencyConflictResolver.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/conflict/TotalRecencyConflictResolver.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.conflict;
+
+import org.drools.reteoo.ReteTuple;
+import org.drools.spi.Activation;
+import org.drools.spi.ConflictResolver;
+
+/**
+ * A conflict resolver that compares the total recency of a tuple when 
+ * determining firing order.
+ * 
+ * @author <a href="mailto:tirelli at post.com">Edson Tirelli</a>
+ * 
+ * @version $Id: TotalRecencyConflictResolver.java 13028 2007-07-03 04:01:41Z fmeyer $
+ */
+public class TotalRecencyConflictResolver extends AbstractConflictResolver {
+    // ----------------------------------------------------------------------
+    // Class members
+    // ----------------------------------------------------------------------
+
+    /**
+     * 
+     */
+    private static final long                         serialVersionUID = 400L;
+    /** Singleton instance. */
+    private static final TotalRecencyConflictResolver INSTANCE         = new TotalRecencyConflictResolver();
+
+    // ----------------------------------------------------------------------
+    // Class methods
+    // ----------------------------------------------------------------------
+
+    /**
+     * Retrieve the singleton instance.
+     * 
+     * @return The singleton instance.
+     */
+    public static ConflictResolver getInstance() {
+        return TotalRecencyConflictResolver.INSTANCE;
+    }
+
+    // ----------------------------------------------------------------------
+    // Constructors
+    // ----------------------------------------------------------------------
+
+    /**
+     * Construct.
+     */
+    public TotalRecencyConflictResolver() {
+        // intentionally left blank
+    }
+
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+    /**
+     * @see ConflictResolver
+     */
+    public int compare(final Activation lhs,
+                       final Activation rhs) {
+        long leftRecency = 0;
+        long rightRecency = 0;
+        if ( lhs.getTuple() instanceof ReteTuple ) {
+            leftRecency = (lhs.getTuple()).getRecency();
+        }
+        if ( rhs.getTuple() instanceof ReteTuple ) {
+            rightRecency = (rhs.getTuple()).getRecency();
+        }
+        return (rightRecency > leftRecency) ? 1 : (rightRecency < leftRecency) ? -1 : 0;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ActivationCancelledEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ActivationCancelledEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ActivationCancelledEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,35 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.Activation;
+
+public class ActivationCancelledEvent extends ActivationEvent {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    public ActivationCancelledEvent(final Activation activation) {
+        super( activation );
+    }
+
+    public String toString() {
+        return "<==[ActivationCancelled(" + getActivation().getActivationNumber() + "): rule=" + getActivation().getRule().getName() + "; tuple=" + getActivation().getTuple() + "]";
+        //return "<==[ActivationCancelled: rule=" + getActivation().getRule().getName() + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ActivationCreatedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ActivationCreatedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ActivationCreatedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,40 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.Activation;
+
+public class ActivationCreatedEvent extends ActivationEvent {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    public ActivationCreatedEvent(final Activation activation) {
+        super( activation );
+    }
+
+    public String toString() {
+        return "==>[ActivationCreated(" + getActivation().getActivationNumber() + "): rule=" + getActivation().getRule().getName() + "; tuple=" + getActivation().getTuple() + "]";
+        //        if (getActivation().getRule().getName().equals("fiSeating")) {
+        //            return "==>[ActivationCreated: rule=" + getActivation().getRule().getName() + "; tuple=" + getActivation().getTuple() + "]";
+        //        } else {
+        //            return "==>[ActivationCreated: rule=" + getActivation().getRule().getName() + "]";
+        //        }
+
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ActivationEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ActivationEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ActivationEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,38 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.EventObject;
+
+import org.drools.spi.Activation;
+
+public class ActivationEvent extends EventObject {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    public ActivationEvent(final Activation activation) {
+        super( activation );
+    }
+
+    public Activation getActivation() {
+        return (Activation) getSource();
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterActivationFiredEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterActivationFiredEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterActivationFiredEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,35 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.Activation;
+
+public class AfterActivationFiredEvent extends ActivationEvent {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    public AfterActivationFiredEvent(final Activation activation) {
+        super( activation );
+    }
+
+    public String toString() {
+        //return "[AfterActivationFired: rule=" + getActivation().getRule().getName() + "; tuple=" + getActivation().getTuple() + "]";
+        return "[AfterActivationFired(" + getActivation().getActivationNumber() + "): rule=" + getActivation().getRule().getName() + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterFunctionRemovedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterFunctionRemovedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterFunctionRemovedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,41 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.RuleBase;
+import org.drools.rule.Package;
+
+public class AfterFunctionRemovedEvent extends RuleBaseEvent {
+
+    private static final long serialVersionUID = 400L;
+
+    public AfterFunctionRemovedEvent(final RuleBase ruleBase,
+                                     final Package pkg,
+                                     final String function) {
+        super( ruleBase,
+               pkg,
+               function );
+    }
+
+    public Object getSource() {
+        return super.getRule();
+    }
+
+    public String toString() {
+        return "[AfterFunctionRemoved: package=" + getPackage() + " function=" + getFunction() + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterPackageAddedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterPackageAddedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterPackageAddedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,35 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.RuleBase;
+import org.drools.rule.Package;
+
+public class AfterPackageAddedEvent extends RuleBaseEvent {
+
+    private static final long serialVersionUID = 400L;
+
+    public AfterPackageAddedEvent(final RuleBase ruleBase,
+                                  final Package pkg) {
+        super( ruleBase,
+               pkg );
+    }
+
+    public String toString() {
+        return "[AfterPackageAdded: package=" + getPackage() + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterPackageRemovedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterPackageRemovedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterPackageRemovedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,35 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.RuleBase;
+import org.drools.rule.Package;
+
+public class AfterPackageRemovedEvent extends RuleBaseEvent {
+
+    private static final long serialVersionUID = 400L;
+
+    public AfterPackageRemovedEvent(final RuleBase ruleBase,
+                                    final Package pkg) {
+        super( ruleBase,
+               pkg );
+    }
+
+    public String toString() {
+        return "[AfterPackageRemoved: package=" + getPackage() + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterRuleAddedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterRuleAddedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterRuleAddedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,42 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.RuleBase;
+import org.drools.rule.Package;
+import org.drools.rule.Rule;
+
+public class AfterRuleAddedEvent extends RuleBaseEvent {
+
+    private static final long serialVersionUID = 400L;
+
+    public AfterRuleAddedEvent(final RuleBase ruleBase,
+                               final Package pkg,
+                               final Rule rule) {
+        super( ruleBase,
+               pkg,
+               rule );
+    }
+
+    public Object getSource() {
+        return super.getRule();
+    }
+
+    public String toString() {
+        return "[AfterRuleAdded: package=" + getPackage() + " rule=" + getRule() + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterRuleBaseLockedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterRuleBaseLockedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterRuleBaseLockedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,32 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.RuleBase;
+
+public class AfterRuleBaseLockedEvent extends RuleBaseEvent {
+
+    private static final long serialVersionUID = 400L;
+
+    public AfterRuleBaseLockedEvent(final RuleBase ruleBase) {
+        super( ruleBase );
+    }
+
+    public String toString() {
+        return "[AfterRuleBaseLocked: ruleBase=" + getRuleBase() + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterRuleBaseUnlockedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterRuleBaseUnlockedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterRuleBaseUnlockedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,32 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.RuleBase;
+
+public class AfterRuleBaseUnlockedEvent extends RuleBaseEvent {
+
+    private static final long serialVersionUID = 400L;
+
+    public AfterRuleBaseUnlockedEvent(final RuleBase ruleBase) {
+        super( ruleBase );
+    }
+
+    public String toString() {
+        return "[AfterRuleBaseUnlocked: ruleBase=" + getRuleBase() + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterRuleRemovedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterRuleRemovedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AfterRuleRemovedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,42 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.RuleBase;
+import org.drools.rule.Package;
+import org.drools.rule.Rule;
+
+public class AfterRuleRemovedEvent extends RuleBaseEvent {
+
+    private static final long serialVersionUID = 400L;
+
+    public AfterRuleRemovedEvent(final RuleBase ruleBase,
+                                 final Package pkg,
+                                 final Rule rule) {
+        super( ruleBase,
+               pkg,
+               rule );
+    }
+
+    public Object getSource() {
+        return super.getRule();
+    }
+
+    public String toString() {
+        return "[AfterRuleRemoved: package=" + getPackage() + " rule=" + getRule() + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AgendaEventListener.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AgendaEventListener.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AgendaEventListener.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,43 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.EventListener;
+
+import org.drools.WorkingMemory;
+
+public interface AgendaEventListener
+    extends
+    EventListener {
+    void activationCreated(ActivationCreatedEvent event,
+                           WorkingMemory workingMemory);
+
+    void activationCancelled(ActivationCancelledEvent event,
+                             WorkingMemory workingMemory);
+
+    void beforeActivationFired(BeforeActivationFiredEvent event,
+                               WorkingMemory workingMemory);
+
+    void afterActivationFired(AfterActivationFiredEvent event,
+                              WorkingMemory workingMemory);
+
+    void agendaGroupPopped(AgendaGroupPoppedEvent event,
+                           WorkingMemory workingMemory);
+
+    void agendaGroupPushed(AgendaGroupPushedEvent event,
+                           WorkingMemory workingMemory);
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AgendaEventSupport.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AgendaEventSupport.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AgendaEventSupport.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,155 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.drools.WorkingMemory;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.Activation;
+import org.drools.spi.AgendaGroup;
+
+/**
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris </a>
+ */
+public class AgendaEventSupport
+    implements
+    Serializable {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+    private final List<AgendaEventListener>        listeners        = new CopyOnWriteArrayList<AgendaEventListener>();
+
+    public AgendaEventSupport() {
+    }
+
+    public void addEventListener(final AgendaEventListener listener) {
+        if ( !this.listeners.contains( listener ) ) {
+            this.listeners.add( listener );
+        }
+    }
+
+    public void removeEventListener(final AgendaEventListener listener) {
+        this.listeners.remove( listener );
+    }
+
+    public List getEventListeners() {
+        
+        return Collections.unmodifiableList( this.listeners );
+    }
+
+    public int size() {
+        return this.listeners.size();
+    }
+
+    public boolean isEmpty() {
+        return this.listeners.isEmpty();
+    }
+
+    public void fireActivationCreated(final Activation activation,
+                                      final WorkingMemory workingMemory) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final ActivationCreatedEvent event = new ActivationCreatedEvent( activation );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((AgendaEventListener) this.listeners.get( i )).activationCreated( event,
+                                                                               workingMemory );
+        }
+    }
+
+    public void fireActivationCancelled(final Activation activation,
+                                        final WorkingMemory workingMemory) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final ActivationCancelledEvent event = new ActivationCancelledEvent( activation );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((AgendaEventListener) this.listeners.get( i )).activationCancelled( event,
+                                                                                 workingMemory );
+        }
+    }
+
+    public void fireBeforeActivationFired(final Activation activation,
+                                          final WorkingMemory workingMemory) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final BeforeActivationFiredEvent event = new BeforeActivationFiredEvent( activation );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((AgendaEventListener) this.listeners.get( i )).beforeActivationFired( event,
+                                                                                   workingMemory );
+        }
+    }
+
+    public void fireAfterActivationFired(final Activation activation,
+                                         final InternalWorkingMemory workingMemory) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final AfterActivationFiredEvent event = new AfterActivationFiredEvent( activation );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((AgendaEventListener) this.listeners.get( i )).afterActivationFired( event,
+                                                                                  workingMemory );
+        }
+    }
+
+    public void fireAgendaGroupPopped(final AgendaGroup agendaGroup,
+                                      final InternalWorkingMemory workingMemory) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final AgendaGroupPoppedEvent event = new AgendaGroupPoppedEvent( agendaGroup );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((AgendaEventListener) this.listeners.get( i )).agendaGroupPopped( event,
+                                                                               workingMemory );
+        }
+    }
+
+    public void fireAgendaGroupPushed(final AgendaGroup agendaGroup,
+                                      final InternalWorkingMemory workingMemory) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final AgendaGroupPushedEvent event = new AgendaGroupPushedEvent( agendaGroup );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((AgendaEventListener) this.listeners.get( i )).agendaGroupPushed( event,
+                                                                               workingMemory );
+        }
+    }
+
+    public void reset() {
+        this.listeners.clear();
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AgendaGroupEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AgendaGroupEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AgendaGroupEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,38 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.EventObject;
+
+import org.drools.spi.AgendaGroup;
+
+public class AgendaGroupEvent extends EventObject {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    public AgendaGroupEvent(final AgendaGroup agendaGroup) {
+        super( agendaGroup );
+    }
+
+    public AgendaGroup getAgendaGroup() {
+        return (AgendaGroup) getSource();
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AgendaGroupPoppedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AgendaGroupPoppedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AgendaGroupPoppedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,34 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.AgendaGroup;
+
+public class AgendaGroupPoppedEvent extends AgendaGroupEvent {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    public AgendaGroupPoppedEvent(final AgendaGroup agendaGroup) {
+        super( agendaGroup );
+    }
+
+    public String toString() {
+        return "<==[AgendaGroupPoppedEvent(" + getAgendaGroup().getName() + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AgendaGroupPushedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AgendaGroupPushedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/AgendaGroupPushedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,34 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.AgendaGroup;
+
+public class AgendaGroupPushedEvent extends AgendaGroupEvent {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    public AgendaGroupPushedEvent(final AgendaGroup agendaGroup) {
+        super( agendaGroup );
+    }
+
+    public String toString() {
+        return ">==[AgendaGroupPushedEvent(" + getAgendaGroup().getName() + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeActivationFiredEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeActivationFiredEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeActivationFiredEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,35 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.Activation;
+
+public class BeforeActivationFiredEvent extends ActivationEvent {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    public BeforeActivationFiredEvent(final Activation activation) {
+        super( activation );
+    }
+
+    public String toString() {
+        return "[BeforeActivationFired: rule=" + getActivation().getRule().getName() + "; tuple=" + getActivation().getTuple() + "]";
+        //return "[BeforeActivationFired(" + getActivation().getActivationNumber() + "): rule=" + getActivation().getRule().getName() + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeFunctionRemovedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeFunctionRemovedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeFunctionRemovedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,41 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.RuleBase;
+import org.drools.rule.Package;
+
+public class BeforeFunctionRemovedEvent extends RuleBaseEvent {
+
+    private static final long serialVersionUID = 400L;
+
+    public BeforeFunctionRemovedEvent(final RuleBase ruleBase,
+                                      final Package pkg,
+                                      final String function) {
+        super( ruleBase,
+               pkg,
+               function );
+    }
+
+    public Object getSource() {
+        return super.getRule();
+    }
+
+    public String toString() {
+        return "[BeforeFunctionRemoved: package=" + getPackage() + " function=" + getFunction() + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforePackageAddedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforePackageAddedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforePackageAddedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,35 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.RuleBase;
+import org.drools.rule.Package;
+
+public class BeforePackageAddedEvent extends RuleBaseEvent {
+
+    private static final long serialVersionUID = 400L;
+
+    public BeforePackageAddedEvent(final RuleBase ruleBase,
+                                   final Package pkg) {
+        super( ruleBase,
+               pkg );
+    }
+
+    public String toString() {
+        return "[BeforePackageAdded: package=" + getPackage() + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforePackageRemovedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforePackageRemovedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforePackageRemovedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,35 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.RuleBase;
+import org.drools.rule.Package;
+
+public class BeforePackageRemovedEvent extends RuleBaseEvent {
+
+    private static final long serialVersionUID = 400L;
+
+    public BeforePackageRemovedEvent(final RuleBase ruleBase,
+                                     final Package pkg) {
+        super( ruleBase,
+               pkg );
+    }
+
+    public String toString() {
+        return "[BeforePackageRemoved: package=" + getPackage() + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeRuleAddedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeRuleAddedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeRuleAddedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,42 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.RuleBase;
+import org.drools.rule.Package;
+import org.drools.rule.Rule;
+
+public class BeforeRuleAddedEvent extends RuleBaseEvent {
+
+    private static final long serialVersionUID = 400L;
+
+    public BeforeRuleAddedEvent(final RuleBase ruleBase,
+                                final Package pkg,
+                                final Rule rule) {
+        super( ruleBase,
+               pkg,
+               rule );
+    }
+
+    public Object getSource() {
+        return super.getRule();
+    }
+
+    public String toString() {
+        return "[BeforeRuleAdded: package=" + getPackage() + " rule=" + getRule() + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeRuleBaseLockedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeRuleBaseLockedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeRuleBaseLockedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,32 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.RuleBase;
+
+public class BeforeRuleBaseLockedEvent extends RuleBaseEvent {
+
+    private static final long serialVersionUID = 400L;
+
+    public BeforeRuleBaseLockedEvent(final RuleBase ruleBase) {
+        super( ruleBase );
+    }
+
+    public String toString() {
+        return "[BeforeRuleBaseLocked: ruleBase=" + getRuleBase() + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeRuleBaseUnlockedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeRuleBaseUnlockedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeRuleBaseUnlockedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,32 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.RuleBase;
+
+public class BeforeRuleBaseUnlockedEvent extends RuleBaseEvent {
+
+    private static final long serialVersionUID = 400L;
+
+    public BeforeRuleBaseUnlockedEvent(final RuleBase ruleBase) {
+        super( ruleBase );
+    }
+
+    public String toString() {
+        return "[BeforeRuleBaseUnlocked: ruleBase=" + getRuleBase() + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeRuleRemovedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeRuleRemovedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/BeforeRuleRemovedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,42 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.RuleBase;
+import org.drools.rule.Package;
+import org.drools.rule.Rule;
+
+public class BeforeRuleRemovedEvent extends RuleBaseEvent {
+
+    private static final long serialVersionUID = 400L;
+
+    public BeforeRuleRemovedEvent(final RuleBase ruleBase,
+                                  final Package pkg,
+                                  final Rule rule) {
+        super( ruleBase,
+               pkg,
+               rule );
+    }
+
+    public Object getSource() {
+        return super.getRule();
+    }
+
+    public String toString() {
+        return "[BeforeRuleRemoved: package=" + getPackage() + " rule=" + getRule() + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DebugAgendaEventListener.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DebugAgendaEventListener.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DebugAgendaEventListener.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,58 @@
+package org.drools.event;
+
+import org.drools.WorkingMemory;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class DebugAgendaEventListener
+    implements
+    AgendaEventListener {
+    public DebugAgendaEventListener() {
+        // intentionally left blank
+    }
+
+    public void activationCreated(final ActivationCreatedEvent event,
+                                  final WorkingMemory workingMemory) {
+        System.err.println( event );
+    }
+
+    public void activationCancelled(final ActivationCancelledEvent event,
+                                    final WorkingMemory workingMemory) {
+        System.err.println( event );
+    }
+
+    public void beforeActivationFired(final BeforeActivationFiredEvent event,
+                                      final WorkingMemory workingMemory) {
+        System.err.println( event );
+    }
+
+    public void afterActivationFired(final AfterActivationFiredEvent event,
+                                     final WorkingMemory workingMemory) {
+        System.err.println( event );
+    }
+
+    public void agendaGroupPopped(final AgendaGroupPoppedEvent event,
+                                  final WorkingMemory workingMemory) {
+        System.err.println( event );
+    }
+
+    public void agendaGroupPushed(final AgendaGroupPushedEvent event,
+                                  final WorkingMemory workingMemory) {
+        System.err.println( event );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DebugRuleFlowEventListener.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DebugRuleFlowEventListener.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DebugRuleFlowEventListener.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,63 @@
+package org.drools.event;
+
+import org.drools.WorkingMemory;
+
+public class DebugRuleFlowEventListener
+    implements
+    RuleFlowEventListener {
+
+    public void beforeRuleFlowCompleted(final RuleFlowCompletedEvent event,
+                                        final WorkingMemory workingMemory) {
+        System.err.println( event );
+    }
+
+    public void afterRuleFlowCompleted(final RuleFlowCompletedEvent event,
+                                       final WorkingMemory workingMemory) {
+        System.err.println(event);
+    }
+
+    public void beforeRuleFlowGroupActivated(
+            final RuleFlowGroupActivatedEvent event,
+            final WorkingMemory workingMemory) {
+        System.err.println( event );
+    }
+
+    public void afterRuleFlowGroupActivated(
+            final RuleFlowGroupActivatedEvent event,
+            final WorkingMemory workingMemory) {
+        System.err.println( event );
+    }
+
+    public void beforeRuleFlowGroupDeactivated(
+            final RuleFlowGroupDeactivatedEvent event,
+            final WorkingMemory workingMemory) {
+        System.err.println( event );
+    }
+
+    public void afterRuleFlowGroupDeactivated(
+            final RuleFlowGroupDeactivatedEvent event,
+            final WorkingMemory workingMemory) {
+        System.err.println( event );
+    }
+
+    public void beforeRuleFlowStarted(final RuleFlowStartedEvent event,
+                                      final WorkingMemory workingMemory) {
+        System.err.println( event );
+    }
+
+    public void afterRuleFlowStarted(final RuleFlowStartedEvent event,
+                                     final WorkingMemory workingMemory) {
+        System.err.println(event);
+    }
+
+    public void afterRuleFlowNodeTriggered(final RuleFlowNodeTriggeredEvent event,
+                                           final WorkingMemory workingMemory) {
+        System.err.println(event);
+    }
+
+    public void beforeRuleFlowNodeTriggered(final RuleFlowNodeTriggeredEvent event,
+                                            final WorkingMemory workingMemory) {
+        System.err.println(event);
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DebugWorkingMemoryEventListener.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DebugWorkingMemoryEventListener.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DebugWorkingMemoryEventListener.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,38 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class DebugWorkingMemoryEventListener
+    implements
+    WorkingMemoryEventListener {
+    public DebugWorkingMemoryEventListener() {
+        // intentionally left blank
+    }
+
+    public void objectInserted(final ObjectInsertedEvent event) {
+        System.err.println( event );
+    }
+
+    public void objectUpdated(final ObjectUpdatedEvent event) {
+        System.err.println( event );
+    }
+
+    public void objectRetracted(final ObjectRetractedEvent event) {
+        System.err.println( event );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DefaultAgendaEventListener.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DefaultAgendaEventListener.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DefaultAgendaEventListener.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,57 @@
+package org.drools.event;
+
+import org.drools.WorkingMemory;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class DefaultAgendaEventListener
+    implements
+    AgendaEventListener {
+    public DefaultAgendaEventListener() {
+        // intentionally left blank
+    }
+
+    public void activationCreated(final ActivationCreatedEvent event,
+                                  final WorkingMemory workingMemory) {
+        // intentionally left blank
+    }
+
+    public void activationCancelled(final ActivationCancelledEvent event,
+                                    final WorkingMemory workingMemory) {
+        // intentionally left blank
+    }
+
+    public void beforeActivationFired(final BeforeActivationFiredEvent event,
+                                      final WorkingMemory workingMemory) {
+        // intentionally left blank
+    }
+
+    public void afterActivationFired(final AfterActivationFiredEvent event,
+                                     final WorkingMemory workingMemory) {
+        // intentionally left blank
+    }
+
+    public void agendaGroupPopped(final AgendaGroupPoppedEvent event,
+                                  final WorkingMemory workingMemory) {
+        // intentionally left blank
+    }
+
+    public void agendaGroupPushed(final AgendaGroupPushedEvent event,
+                                  final WorkingMemory workingMemory) {
+        // intentionally left blank
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DefaultRuleBaseEventListener.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DefaultRuleBaseEventListener.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DefaultRuleBaseEventListener.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,78 @@
+package org.drools.event;
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+public class DefaultRuleBaseEventListener
+    implements
+    RuleBaseEventListener {
+
+    public void afterFunctionRemoved(AfterFunctionRemovedEvent event) {
+        // intentionally left blank
+    }
+
+    public void afterPackageAdded(AfterPackageAddedEvent event) {
+        // intentionally left blank
+    }
+
+    public void afterPackageRemoved(AfterPackageRemovedEvent event) {
+        // intentionally left blank
+    }
+
+    public void afterRuleAdded(AfterRuleAddedEvent event) {
+        // intentionally left blank
+    }
+
+    public void afterRuleBaseLocked(AfterRuleBaseLockedEvent event) {
+        // intentionally left blank
+    }
+
+    public void afterRuleBaseUnlocked(AfterRuleBaseUnlockedEvent event) {
+        // intentionally left blank
+    }
+
+    public void afterRuleRemoved(AfterRuleRemovedEvent event) {
+        // intentionally left blank
+    }
+
+    public void beforeFunctionRemoved(BeforeFunctionRemovedEvent event) {
+        // intentionally left blank
+    }
+
+    public void beforePackageAdded(BeforePackageAddedEvent event) {
+        // intentionally left blank
+    }
+
+    public void beforePackageRemoved(BeforePackageRemovedEvent event) {
+        // intentionally left blank
+    }
+
+    public void beforeRuleAdded(BeforeRuleAddedEvent event) {
+        // intentionally left blank
+    }
+
+    public void beforeRuleBaseLocked(BeforeRuleBaseLockedEvent event) {
+        // intentionally left blank
+    }
+
+    public void beforeRuleBaseUnlocked(BeforeRuleBaseUnlockedEvent event) {
+        // intentionally left blank
+    }
+
+    public void beforeRuleRemoved(BeforeRuleRemovedEvent event) {
+        // intentionally left blank
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DefaultRuleFlowEventListener.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DefaultRuleFlowEventListener.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DefaultRuleFlowEventListener.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,59 @@
+package org.drools.event;
+
+import org.drools.WorkingMemory;
+
+public class DefaultRuleFlowEventListener
+    implements
+    RuleFlowEventListener {
+
+    public void beforeRuleFlowCompleted(final RuleFlowCompletedEvent event,
+                                        final WorkingMemory workingMemory) {
+        // intentionally left blank
+    }
+
+    public void afterRuleFlowCompleted(final RuleFlowCompletedEvent event,
+                                       final WorkingMemory workingMemory) {
+        // intentionally left blank
+    }
+
+    public void beforeRuleFlowGroupActivated(final RuleFlowGroupActivatedEvent event,
+                                             final WorkingMemory workingMemory) {
+        // intentionally left blank
+    }
+
+    public void afterRuleFlowGroupActivated(final RuleFlowGroupActivatedEvent event,
+                                            final WorkingMemory workingMemory) {
+        // intentionally left blank
+    }
+
+    public void beforeRuleFlowGroupDeactivated(final RuleFlowGroupDeactivatedEvent event,
+                                               final WorkingMemory workingMemory) {
+        // intentionally left blank
+    }
+
+    public void afterRuleFlowGroupDeactivated(final RuleFlowGroupDeactivatedEvent event,
+                                              final WorkingMemory workingMemory) {
+        // intentionally left blank
+    }
+
+    public void beforeRuleFlowStarted(final RuleFlowStartedEvent event,
+                                      final WorkingMemory workingMemory) {
+        // intentionally left blank
+    }
+
+    public void afterRuleFlowStarted(final RuleFlowStartedEvent event,
+                                     final WorkingMemory workingMemory) {
+        // intentionally left blank
+    }
+
+    public void afterRuleFlowNodeTriggered(final RuleFlowNodeTriggeredEvent event,
+                                           final WorkingMemory workingMemory) {
+        // intentionally left blank
+    }
+
+    public void beforeRuleFlowNodeTriggered(final RuleFlowNodeTriggeredEvent event,
+                                            final WorkingMemory workingMemory) {
+        // intentionally left blank
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DefaultWorkingMemoryEventListener.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DefaultWorkingMemoryEventListener.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/DefaultWorkingMemoryEventListener.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,37 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class DefaultWorkingMemoryEventListener
+    implements
+    WorkingMemoryEventListener {
+    public DefaultWorkingMemoryEventListener() {
+        // intentionally left blank
+    }
+
+    public void objectInserted(final ObjectInsertedEvent event) {
+        // intentionally left blank
+    }
+
+    public void objectUpdated(final ObjectUpdatedEvent event) {
+        // intentionally left blank
+    }
+
+    public void objectRetracted(final ObjectRetractedEvent event) {
+        // intentionally left blank
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ObjectInsertedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ObjectInsertedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ObjectInsertedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,54 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.FactHandle;
+import org.drools.WorkingMemory;
+import org.drools.spi.PropagationContext;
+
+public class ObjectInsertedEvent extends WorkingMemoryEvent {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    private final FactHandle  handle;
+
+    private final Object      object;
+
+    public ObjectInsertedEvent(final WorkingMemory workingMemory,
+                               final PropagationContext propagationContext,
+                               final FactHandle handle,
+                               final Object object) {
+        super( workingMemory,
+               propagationContext );
+        this.handle = handle;
+        this.object = object;
+    }
+
+    public FactHandle getFactHandle() {
+        return this.handle;
+    }
+
+    public Object getObject() {
+        return this.object;
+    }
+
+    public String toString() {
+        return "[ObjectInserted: handle=" + this.handle + "; object=" + this.object + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ObjectRetractedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ObjectRetractedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ObjectRetractedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,54 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.FactHandle;
+import org.drools.WorkingMemory;
+import org.drools.spi.PropagationContext;
+
+public class ObjectRetractedEvent extends WorkingMemoryEvent {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    private final FactHandle  handle;
+
+    private final Object      oldObject;
+
+    public ObjectRetractedEvent(final WorkingMemory workingMemory,
+                                final PropagationContext propagationContext,
+                                final FactHandle handle,
+                                final Object oldObject) {
+        super( workingMemory,
+               propagationContext );
+        this.handle = handle;
+        this.oldObject = oldObject;
+    }
+
+    public FactHandle getFactHandle() {
+        return this.handle;
+    }
+
+    public Object getOldObject() {
+        return this.oldObject;
+    }
+
+    public String toString() {
+        return "[ObjectRetracted: handle=" + this.handle + "; old_object=" + this.oldObject + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ObjectUpdatedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ObjectUpdatedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/ObjectUpdatedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,62 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.FactHandle;
+import org.drools.WorkingMemory;
+import org.drools.spi.PropagationContext;
+
+public class ObjectUpdatedEvent extends WorkingMemoryEvent {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    private final FactHandle  handle;
+
+    private final Object      oldObject;
+
+    private final Object      object;
+
+    public ObjectUpdatedEvent(final WorkingMemory workingMemory,
+                              final PropagationContext propagationContext,
+                              final FactHandle handle,
+                              final Object oldObject,
+                              final Object object) {
+        super( workingMemory,
+               propagationContext );
+        this.handle = handle;
+        this.oldObject = oldObject;
+        this.object = object;
+    }
+
+    public FactHandle getFactHandle() {
+        return this.handle;
+    }
+
+    public Object getOldObject() {
+        return this.oldObject;
+    }
+
+    public Object getObject() {
+        return this.object;
+    }
+
+    public String toString() {
+        return "[ObjectUpdated: handle=" + this.handle + "; old_object=" + this.oldObject + "; new_object=" + this.object + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleBaseEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleBaseEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleBaseEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,86 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.EventObject;
+
+import org.drools.RuleBase;
+import org.drools.rule.Package;
+import org.drools.rule.Rule;
+
+public class RuleBaseEvent extends EventObject {
+
+    private static final long serialVersionUID = 400L;
+    private final RuleBase    ruleBase;
+    private final Package     pkg;
+    private final Rule        rule;
+    private final String      function;
+
+    public RuleBaseEvent(final RuleBase ruleBase) {
+        super( ruleBase );
+        this.ruleBase = ruleBase;
+        this.pkg = null;
+        this.rule = null;
+        this.function = null;
+    }
+
+    public RuleBaseEvent(final RuleBase ruleBase,
+                         final Package pkg) {
+        super( ruleBase );
+        this.ruleBase = ruleBase;
+        this.pkg = pkg;
+        this.rule = null;
+        this.function = null;
+    }
+
+    public RuleBaseEvent(final RuleBase ruleBase,
+                         final Package pkg,
+                         final Rule rule) {
+        super( ruleBase );
+        this.ruleBase = ruleBase;
+        this.pkg = pkg;
+        this.rule = rule;
+        this.function = null;
+    }
+
+    public RuleBaseEvent(final RuleBase ruleBase,
+                         final Package pkg,
+                         final String function) {
+        super( ruleBase );
+        this.ruleBase = ruleBase;
+        this.pkg = pkg;
+        this.rule = null;
+        this.function = function;
+    }
+
+    public RuleBase getRuleBase() {
+        return this.ruleBase;
+    }
+
+    public Package getPackage() {
+        return this.pkg;
+    }
+
+    public Rule getRule() {
+        return this.rule;
+    }
+
+    public String getFunction() {
+        return this.function;
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleBaseEventListener.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleBaseEventListener.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleBaseEventListener.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,93 @@
+package org.drools.event;
+
+import java.util.EventListener;
+
+public interface RuleBaseEventListener
+    extends
+    EventListener {
+
+    /**
+     * Method called before a new package is added to the rule base
+     * @param event
+     */
+    void beforePackageAdded(BeforePackageAddedEvent event);
+
+    /**
+     * Method called after a new package is added to the rule base
+     * @param event
+     */
+    void afterPackageAdded(AfterPackageAddedEvent event);
+
+    /**
+     * Method called before a package is removed from the rule base
+     * @param event
+     */
+    void beforePackageRemoved(BeforePackageRemovedEvent event);
+
+    /**
+     * Method called after a package is removed from the rule base
+     * @param event
+     */
+    void afterPackageRemoved(AfterPackageRemovedEvent event);
+
+    /**
+     * Method called before a rule base is locked
+     * @param event
+     */
+    void beforeRuleBaseLocked(BeforeRuleBaseLockedEvent event);
+
+    /**
+     * Method called after a rule base is locked
+     * @param event
+     */
+    void afterRuleBaseLocked(AfterRuleBaseLockedEvent event);
+
+    /**
+     * Method called before a rule base is unlocked
+     * @param event
+     */
+    void beforeRuleBaseUnlocked(BeforeRuleBaseUnlockedEvent event);
+
+    /**
+     * Method called after a rule base is unlocked
+     * @param event
+     */
+    void afterRuleBaseUnlocked(AfterRuleBaseUnlockedEvent event);
+
+    /**
+     * Method called before a new rule is added to the rule base
+     * @param event
+     */
+    void beforeRuleAdded(BeforeRuleAddedEvent event);
+
+    /**
+     * Method called after a new rule is added to the rule base
+     * @param event
+     */
+    void afterRuleAdded(AfterRuleAddedEvent event);
+
+    /**
+     * Method called before a rule is removed from the rule base
+     * @param event
+     */
+    void beforeRuleRemoved(BeforeRuleRemovedEvent event);
+
+    /**
+     * Method called after a rule is removed from the rule base
+     * @param event
+     */
+    void afterRuleRemoved(AfterRuleRemovedEvent event);
+
+    /**
+     * Method called before a function is removed from the rule base
+     * @param event
+     */
+    void beforeFunctionRemoved(BeforeFunctionRemovedEvent event);
+
+    /**
+     * Method called after a function is removed from the rule base
+     * @param event
+     */
+    void afterFunctionRemoved(AfterFunctionRemovedEvent event);
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleBaseEventSupport.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleBaseEventSupport.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleBaseEventSupport.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,277 @@
+package org.drools.event;
+
+/*
+ * Copyright 2007 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.
+ */
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EventListener;
+import java.util.List;
+
+import org.drools.RuleBase;
+import org.drools.rule.Rule;
+import org.drools.rule.Package;
+
+import java.util.Iterator;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * 
+ * @author etirelli
+ */
+public class RuleBaseEventSupport
+    implements
+    Serializable {
+    /**
+     * 
+     */
+    private static final long                 serialVersionUID = 400L;
+    private final List<RuleBaseEventListener> listeners        = new CopyOnWriteArrayList<RuleBaseEventListener>();
+    private transient RuleBase                ruleBase;
+
+    public RuleBaseEventSupport(final RuleBase ruleBase) {
+        this.ruleBase = ruleBase;
+    }
+
+    public void addEventListener(final RuleBaseEventListener listener) {
+        if ( !this.listeners.contains( listener ) ) {
+            this.listeners.add( listener );
+        }
+    }
+
+    public void setRuleBase(RuleBase ruleBase) {
+        this.ruleBase = ruleBase;
+    }
+
+    public void removeEventListener(Class cls) {
+        for ( int i = 0; i < this.listeners.size(); ) {
+            RuleBaseEventListener listener = this.listeners.get( i );
+            if ( cls.isAssignableFrom( listener.getClass() ) ) {
+                this.listeners.remove( i );
+            } else {
+                i++;
+            }
+        }
+    }
+
+    public void removeEventListener(final RuleBaseEventListener listener) {
+        this.listeners.remove( listener );
+    }
+
+    public List<RuleBaseEventListener> getEventListeners() {
+        return Collections.unmodifiableList( this.listeners );
+    }
+
+    public int size() {
+        return this.listeners.size();
+    }
+
+    public boolean isEmpty() {
+        return this.listeners.isEmpty();
+    }
+
+    public void fireBeforePackageAdded(final Package newPkg) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final BeforePackageAddedEvent event = new BeforePackageAddedEvent( this.ruleBase,
+                                                                           newPkg );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleBaseEventListener) this.listeners.get( i )).beforePackageAdded( event );
+        }
+    }
+
+    public void fireAfterPackageAdded(final Package newPkg) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final AfterPackageAddedEvent event = new AfterPackageAddedEvent( this.ruleBase,
+                                                                         newPkg );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleBaseEventListener) this.listeners.get( i )).afterPackageAdded( event );
+        }
+    }
+
+    public void fireBeforePackageRemoved(final Package pkg) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final BeforePackageRemovedEvent event = new BeforePackageRemovedEvent( this.ruleBase,
+                                                                               pkg );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleBaseEventListener) this.listeners.get( i )).beforePackageRemoved( event );
+        }
+    }
+
+    public void fireAfterPackageRemoved(final Package pkg) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final AfterPackageRemovedEvent event = new AfterPackageRemovedEvent( this.ruleBase,
+                                                                             pkg );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleBaseEventListener) this.listeners.get( i )).afterPackageRemoved( event );
+        }
+    }
+
+    //--
+    public void fireBeforeRuleBaseLocked() {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final BeforeRuleBaseLockedEvent event = new BeforeRuleBaseLockedEvent( this.ruleBase );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleBaseEventListener) this.listeners.get( i )).beforeRuleBaseLocked( event );
+        }
+    }
+
+    public void fireAfterRuleBaseLocked() {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final AfterRuleBaseLockedEvent event = new AfterRuleBaseLockedEvent( this.ruleBase );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleBaseEventListener) this.listeners.get( i )).afterRuleBaseLocked( event );
+        }
+    }
+
+    public void fireBeforeRuleBaseUnlocked() {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final BeforeRuleBaseUnlockedEvent event = new BeforeRuleBaseUnlockedEvent( this.ruleBase );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleBaseEventListener) this.listeners.get( i )).beforeRuleBaseUnlocked( event );
+        }
+    }
+
+    public void fireAfterRuleBaseUnlocked() {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final AfterRuleBaseUnlockedEvent event = new AfterRuleBaseUnlockedEvent( this.ruleBase );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleBaseEventListener) this.listeners.get( i )).afterRuleBaseUnlocked( event );
+        }
+    }
+
+    public void fireBeforeRuleAdded(final Package newPkg,
+                                    final Rule rule) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final BeforeRuleAddedEvent event = new BeforeRuleAddedEvent( this.ruleBase,
+                                                                     newPkg,
+                                                                     rule );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleBaseEventListener) this.listeners.get( i )).beforeRuleAdded( event );
+        }
+    }
+
+    public void fireAfterRuleAdded(final Package newPkg,
+                                   final Rule rule) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final AfterRuleAddedEvent event = new AfterRuleAddedEvent( this.ruleBase,
+                                                                   newPkg,
+                                                                   rule );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleBaseEventListener) this.listeners.get( i )).afterRuleAdded( event );
+        }
+    }
+
+    public void fireBeforeRuleRemoved(final Package pkg,
+                                      final Rule rule) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final BeforeRuleRemovedEvent event = new BeforeRuleRemovedEvent( this.ruleBase,
+                                                                         pkg,
+                                                                         rule );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleBaseEventListener) this.listeners.get( i )).beforeRuleRemoved( event );
+        }
+    }
+
+    public void fireAfterRuleRemoved(final Package pkg,
+                                     final Rule rule) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final AfterRuleRemovedEvent event = new AfterRuleRemovedEvent( this.ruleBase,
+                                                                       pkg,
+                                                                       rule );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleBaseEventListener) this.listeners.get( i )).afterRuleRemoved( event );
+        }
+    }
+
+    public void fireBeforeFunctionRemoved(final Package pkg,
+                                          final String function) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final BeforeFunctionRemovedEvent event = new BeforeFunctionRemovedEvent( this.ruleBase,
+                                                                                 pkg,
+                                                                                 function );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleBaseEventListener) this.listeners.get( i )).beforeFunctionRemoved( event );
+        }
+    }
+
+    public void fireAfterFunctionRemoved(final Package pkg,
+                                         final String function) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final AfterFunctionRemovedEvent event = new AfterFunctionRemovedEvent( this.ruleBase,
+                                                                               pkg,
+                                                                               function );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleBaseEventListener) this.listeners.get( i )).afterFunctionRemoved( event );
+        }
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowCompletedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowCompletedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowCompletedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,35 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.process.instance.ProcessInstance;
+
+/**
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class RuleFlowCompletedEvent extends RuleFlowEvent {
+
+    private static final long serialVersionUID = 400L;
+
+    public RuleFlowCompletedEvent(final ProcessInstance instance) {
+        super( instance );
+    }
+
+    public String toString() {
+        return "==>[ProcessCompleted(name=" + getRuleFlowProcessInstance().getProcess().getName() + "; id=" + getRuleFlowProcessInstance().getProcess().getId() + ")]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,38 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.EventObject;
+
+import org.drools.process.instance.ProcessInstance;
+
+/**
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class RuleFlowEvent extends EventObject {
+
+    private static final long serialVersionUID = 400L;
+
+    public RuleFlowEvent(final ProcessInstance instance) {
+        super( instance );
+    }
+
+    public ProcessInstance getRuleFlowProcessInstance() {
+        return (ProcessInstance) getSource();
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowEventListener.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowEventListener.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowEventListener.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,60 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.EventListener;
+
+import org.drools.WorkingMemory;
+
+/**
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface RuleFlowEventListener
+    extends
+    EventListener {
+
+    void beforeRuleFlowStarted(RuleFlowStartedEvent event,
+                               WorkingMemory workingMemory);
+
+    void afterRuleFlowStarted(RuleFlowStartedEvent event,
+                              WorkingMemory workingMemory);
+
+    void beforeRuleFlowCompleted(RuleFlowCompletedEvent event,
+                                 WorkingMemory workingMemory);
+
+    void afterRuleFlowCompleted(RuleFlowCompletedEvent event,
+                                WorkingMemory workingMemory);
+
+    void beforeRuleFlowGroupActivated(RuleFlowGroupActivatedEvent event,
+                                      WorkingMemory workingMemory);
+
+    void afterRuleFlowGroupActivated(RuleFlowGroupActivatedEvent event,
+                                     WorkingMemory workingMemory);
+    
+    void beforeRuleFlowGroupDeactivated(RuleFlowGroupDeactivatedEvent event,
+                                        WorkingMemory workingMemory);
+
+    void afterRuleFlowGroupDeactivated(RuleFlowGroupDeactivatedEvent event,
+                                       WorkingMemory workingMemory);
+
+    void beforeRuleFlowNodeTriggered(RuleFlowNodeTriggeredEvent event,
+                                     WorkingMemory workingMemory);
+
+    void afterRuleFlowNodeTriggered(RuleFlowNodeTriggeredEvent event,
+                                    WorkingMemory workingMemory);
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowEventSupport.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowEventSupport.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowEventSupport.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,216 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.drools.common.InternalWorkingMemory;
+import org.drools.process.instance.ProcessInstance;
+import org.drools.spi.RuleFlowGroup;
+import org.drools.workflow.instance.NodeInstance;
+import org.drools.workflow.instance.WorkflowProcessInstance;
+
+/**
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class RuleFlowEventSupport implements Serializable {
+    
+    // TODO separate out process level stuff
+
+    private static final long                 serialVersionUID = 400L;
+    private final List<RuleFlowEventListener> listeners        = new CopyOnWriteArrayList<RuleFlowEventListener>();
+
+    public RuleFlowEventSupport() {
+    }
+
+    public void addEventListener(final RuleFlowEventListener listener) {
+        if ( !this.listeners.contains( listener ) ) {
+            this.listeners.add( listener );
+        }
+    }
+
+    public void removeEventListener(final RuleFlowEventListener listener) {
+        this.listeners.remove( listener );
+    }
+
+    public List getEventListeners() {
+        return Collections.unmodifiableList( this.listeners );
+    }
+
+    public int size() {
+        return this.listeners.size();
+    }
+
+    public boolean isEmpty() {
+        return this.listeners.isEmpty();
+    }
+
+    public void fireBeforeRuleFlowProcessStarted(
+            final ProcessInstance instance,
+            final InternalWorkingMemory workingMemory) {
+        if (this.listeners.isEmpty()) {
+            return;
+        }
+
+        final RuleFlowStartedEvent event = new RuleFlowStartedEvent( instance );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleFlowEventListener) this.listeners.get( i )).beforeRuleFlowStarted( event,
+                                                                                     workingMemory );
+        }
+    }
+
+    public void fireAfterRuleFlowProcessStarted(
+            final ProcessInstance instance,
+            final InternalWorkingMemory workingMemory) {
+        if (this.listeners.isEmpty()) {
+            return;
+        }
+
+        final RuleFlowStartedEvent event = new RuleFlowStartedEvent( instance );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleFlowEventListener) this.listeners.get( i )).afterRuleFlowStarted( event,
+                                                                                    workingMemory );
+        }
+    }
+
+    public void fireBeforeRuleFlowProcessCompleted(
+            final WorkflowProcessInstance instance,
+            final InternalWorkingMemory workingMemory) {
+        if (this.listeners.isEmpty()) {
+            return;
+        }
+
+        final RuleFlowCompletedEvent event = new RuleFlowCompletedEvent( instance );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleFlowEventListener) this.listeners.get( i )).beforeRuleFlowCompleted( event,
+                                                                                       workingMemory );
+        }
+    }
+
+    public void fireAfterRuleFlowProcessCompleted(
+            final WorkflowProcessInstance instance,
+            final InternalWorkingMemory workingMemory) {
+        if (this.listeners.isEmpty()) {
+            return;
+        }
+
+        final RuleFlowCompletedEvent event = new RuleFlowCompletedEvent( instance );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleFlowEventListener) this.listeners.get( i )).afterRuleFlowCompleted( event,
+                                                                                      workingMemory );
+        }
+    }
+
+    public void fireBeforeRuleFlowGroupActivated(final RuleFlowGroup ruleFlowGroup,
+                                                 final InternalWorkingMemory workingMemory) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final RuleFlowGroupActivatedEvent event = new RuleFlowGroupActivatedEvent( ruleFlowGroup );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleFlowEventListener) this.listeners.get( i )).beforeRuleFlowGroupActivated( event,
+                                                                                            workingMemory );
+        }
+    }
+
+    public void fireAfterRuleFlowGroupActivated(final RuleFlowGroup ruleFlowGroup,
+                                                final InternalWorkingMemory workingMemory) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final RuleFlowGroupActivatedEvent event = new RuleFlowGroupActivatedEvent( ruleFlowGroup );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleFlowEventListener) this.listeners.get( i )).afterRuleFlowGroupActivated( event,
+                                                                                           workingMemory );
+        }
+    }
+
+    public void fireBeforeRuleFlowGroupDeactivated(final RuleFlowGroup ruleFlowGroup,
+                                                   final InternalWorkingMemory workingMemory) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final RuleFlowGroupDeactivatedEvent event = new RuleFlowGroupDeactivatedEvent( ruleFlowGroup );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleFlowEventListener) this.listeners.get( i )).beforeRuleFlowGroupDeactivated( event,
+                                                                                              workingMemory );
+        }
+    }
+
+    public void fireAfterRuleFlowGroupDeactivated(final RuleFlowGroup ruleFlowGroup,
+                                                  final InternalWorkingMemory workingMemory) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final RuleFlowGroupDeactivatedEvent event = new RuleFlowGroupDeactivatedEvent( ruleFlowGroup );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleFlowEventListener) this.listeners.get( i )).afterRuleFlowGroupDeactivated( event,
+                                                                                             workingMemory );
+        }
+    }
+
+    public void fireBeforeRuleFlowNodeTriggered(
+            final NodeInstance ruleFlowNodeInstance,
+            final InternalWorkingMemory workingMemory) {
+        if (this.listeners.isEmpty()) {
+            return;
+        }
+
+        final RuleFlowNodeTriggeredEvent event = new RuleFlowNodeTriggeredEvent( ruleFlowNodeInstance );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleFlowEventListener) this.listeners.get( i )).beforeRuleFlowNodeTriggered( event,
+                                                                                           workingMemory );
+        }
+    }
+
+    public void fireAfterRuleFlowNodeTriggered(
+            final NodeInstance ruleFlowNodeInstance,
+            final InternalWorkingMemory workingMemory) {
+        if (this.listeners.isEmpty()) {
+            return;
+        }
+
+        final RuleFlowNodeTriggeredEvent event = new RuleFlowNodeTriggeredEvent( ruleFlowNodeInstance );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((RuleFlowEventListener) this.listeners.get( i )).afterRuleFlowNodeTriggered( event,
+                                                                                          workingMemory );
+        }
+    }
+
+    public void reset() {
+        this.listeners.clear();
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowGroupActivatedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowGroupActivatedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowGroupActivatedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,35 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.RuleFlowGroup;
+
+/**
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class RuleFlowGroupActivatedEvent extends RuleFlowGroupEvent {
+
+    private static final long serialVersionUID = 400L;
+
+    public RuleFlowGroupActivatedEvent(final RuleFlowGroup ruleFlowGroup) {
+        super( ruleFlowGroup );
+    }
+
+    public String toString() {
+        return "==>[RuleFlowGroupActivated(name=" + getRuleFlowGroup().getName() + "; size=" + getRuleFlowGroup().size() + ")]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowGroupDeactivatedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowGroupDeactivatedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowGroupDeactivatedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,35 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.RuleFlowGroup;
+
+/**
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class RuleFlowGroupDeactivatedEvent extends RuleFlowGroupEvent {
+
+    private static final long serialVersionUID = 400L;
+
+    public RuleFlowGroupDeactivatedEvent(final RuleFlowGroup ruleFlowGroup) {
+        super( ruleFlowGroup );
+    }
+
+    public String toString() {
+        return "==>[RuleFlowGroupDeactivated(name=" + getRuleFlowGroup().getName() + "; size=" + getRuleFlowGroup().size() + ")]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowGroupEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowGroupEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowGroupEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,38 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.EventObject;
+
+import org.drools.spi.RuleFlowGroup;
+
+/**
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class RuleFlowGroupEvent extends EventObject {
+
+    private static final long serialVersionUID = 400L;
+
+    public RuleFlowGroupEvent(final RuleFlowGroup ruleFlowGroup) {
+        super( ruleFlowGroup );
+    }
+
+    public RuleFlowGroup getRuleFlowGroup() {
+        return (RuleFlowGroup) getSource();
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowNodeTriggeredEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowNodeTriggeredEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowNodeTriggeredEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,43 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.workflow.instance.NodeInstance;
+
+/**
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class RuleFlowNodeTriggeredEvent extends RuleFlowEvent {
+
+    private static final long serialVersionUID = 400L;
+    
+    private NodeInstance nodeInstance;
+
+    public RuleFlowNodeTriggeredEvent(final NodeInstance nodeInstance) {
+        super( nodeInstance.getProcessInstance() );
+        this.nodeInstance = nodeInstance;
+    }
+    
+    public NodeInstance getRuleFlowNodeInstance() {
+        return nodeInstance;
+    }
+
+    public String toString() {
+        return "==>[WorkflowNodeTriggered(nodeId=" + nodeInstance.getNodeId() + "; id=" + nodeInstance.getId() 
+            + "; processName=" + getRuleFlowProcessInstance().getProcess().getName() + "; processId=" + getRuleFlowProcessInstance().getProcess().getId() + ")]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowStartedEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowStartedEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/RuleFlowStartedEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,35 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.process.instance.ProcessInstance;
+
+/**
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class RuleFlowStartedEvent extends RuleFlowEvent {
+
+    private static final long serialVersionUID = 400L;
+
+    public RuleFlowStartedEvent(final ProcessInstance instance) {
+        super( instance );
+    }
+
+    public String toString() {
+        return "==>[ProcessStarted(name=" + getRuleFlowProcessInstance().getProcess().getName() + "; id=" + getRuleFlowProcessInstance().getProcess().getId() + ")]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/WorkingMemoryEvent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/WorkingMemoryEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/WorkingMemoryEvent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,44 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.EventObject;
+
+import org.drools.WorkingMemory;
+import org.drools.spi.PropagationContext;
+
+public class WorkingMemoryEvent extends EventObject {
+    /**
+     * 
+     */
+    private static final long        serialVersionUID = 400L;
+    private final PropagationContext propagationContext;
+
+    public WorkingMemoryEvent(final WorkingMemory workingMemory,
+                              final PropagationContext propagationContext) {
+        super( workingMemory );
+        this.propagationContext = propagationContext;
+    }
+
+    public WorkingMemory getWorkingMemory() {
+        return (WorkingMemory) getSource();
+    }
+
+    public PropagationContext getPropagationContext() {
+        return this.propagationContext;
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/WorkingMemoryEventListener.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/WorkingMemoryEventListener.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/WorkingMemoryEventListener.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,30 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.EventListener;
+
+public interface WorkingMemoryEventListener
+    extends
+    EventListener {
+    void objectInserted(ObjectInsertedEvent event);
+
+    void objectUpdated(ObjectUpdatedEvent event);
+
+    void objectRetracted(ObjectRetractedEvent event);
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/WorkingMemoryEventSupport.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/WorkingMemoryEventSupport.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/event/WorkingMemoryEventSupport.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,126 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.drools.FactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+
+/**
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris </a>
+ */
+public class WorkingMemoryEventSupport
+    implements
+    Serializable {
+    /**
+     * 
+     */
+    private static final long                      serialVersionUID = 400L;
+    private final List<WorkingMemoryEventListener> listeners        = new CopyOnWriteArrayList<WorkingMemoryEventListener>();
+
+    public WorkingMemoryEventSupport() {
+    }
+
+    public void addEventListener(final WorkingMemoryEventListener listener) {
+        if ( !this.listeners.contains( listener ) ) {
+            this.listeners.add( listener );
+        }
+    }
+
+    public void removeEventListener(final WorkingMemoryEventListener listener) {
+        this.listeners.remove( listener );
+    }
+
+    public List getEventListeners() {
+        return Collections.unmodifiableList( this.listeners );
+    }
+
+    public int size() {
+        return this.listeners.size();
+    }
+
+    public boolean isEmpty() {
+        return this.listeners.isEmpty();
+    }
+
+    public void fireObjectInserted(final PropagationContext propagationContext,
+                                   final FactHandle handle,
+                                   final Object object,
+                                   final InternalWorkingMemory workingMemory) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final ObjectInsertedEvent event = new ObjectInsertedEvent( workingMemory,
+                                                                   propagationContext,
+                                                                   handle,
+                                                                   object );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((WorkingMemoryEventListener) this.listeners.get( i )).objectInserted( event );
+        }
+    }
+
+    public void fireObjectUpdated(final PropagationContext propagationContext,
+                                  final FactHandle handle,
+                                  final Object oldObject,
+                                  final Object object,
+                                  final InternalWorkingMemory workingMemory) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final ObjectUpdatedEvent event = new ObjectUpdatedEvent( workingMemory,
+                                                                 propagationContext,
+                                                                 handle,
+                                                                 oldObject,
+                                                                 object );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((WorkingMemoryEventListener) this.listeners.get( i )).objectUpdated( event );
+        }
+    }
+
+    public void fireObjectRetracted(final PropagationContext propagationContext,
+                                    final FactHandle handle,
+                                    final Object oldObject,
+                                    final InternalWorkingMemory workingMemory) {
+        if ( this.listeners.isEmpty() ) {
+            return;
+        }
+
+        final ObjectRetractedEvent event = new ObjectRetractedEvent( workingMemory,
+                                                                     propagationContext,
+                                                                     handle,
+                                                                     oldObject );
+
+        for ( int i = 0, size = this.listeners.size(); i < size; i++ ) {
+            ((WorkingMemoryEventListener) this.listeners.get( i )).objectRetracted( event );
+        }
+    }
+
+    public void reset() {
+        this.listeners.clear();
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/Fact.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/Fact.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/Fact.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2002-2005 Peter Lin & RuleML.
+ *
+ * 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://ruleml-dev.sourceforge.net/
+ *
+ * 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.facttemplates;
+
+/**
+ * @author Peter Lin
+ * 
+ * Base interface for Facts
+ */
+public interface Fact {
+
+    /**
+     * Return the value at the given field  index
+     * @param id
+     * @return
+     */
+    Object getFieldValue(int index);
+
+    Object getFieldValue(String name);
+
+    void setFieldValue(String name,
+                       Object value);
+
+    void setFieldValue(int index,
+                       Object value);
+
+    /**
+     * Return the unique ID for the fact
+     * @return
+     */
+    long getFactId();
+
+    /**
+     * Return the Deftemplate for the fact
+     * @return
+     */
+    FactTemplate getFactTemplate();
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FactImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FactImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FactImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2002-2006 Peter Lin & RuleML.
+ *
+ * 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://ruleml-dev.sourceforge.net/
+ *
+ * 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.facttemplates;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+//import woolfel.engine.rule.Rule;
+
+/**
+ * @author Peter Lin
+ * 
+ * Deffact is a concrete implementation of Fact interface. It is
+ * equivalent to deffact in CLIPS.
+ */
+public class FactImpl
+    implements
+    Fact,
+    Serializable {
+
+    private static int hashCode(final Object[] array) {
+        final int PRIME = 31;
+        if ( array == null ) {
+            return 0;
+        }
+        int result = 1;
+        for ( int index = 0; index < array.length; index++ ) {
+            result = PRIME * result + (array[index] == null ? 0 : array[index].hashCode());
+        }
+        return result;
+    }
+
+    private FactTemplate factTemplate = null;
+    private Object[]     values       = null;
+    private int          hashCode;
+
+    /**
+     * the Fact id must be unique, since we use it for the indexes
+     */
+    private long         id;
+
+    /**
+     * this is the default constructor
+     * @param instance
+     * @param values
+     */
+    public FactImpl(final FactTemplate template,
+                    final Object[] values,
+                    final long id) {
+        this.factTemplate = template;
+        this.values = values;
+        this.id = id;
+    }
+
+    public FactImpl(final FactTemplate template,
+                    final long id) {
+        this.factTemplate = template;
+        this.values = new Object[template.getNumberOfFields()];
+        this.id = id;
+    }
+
+    /**
+     * Method returns the value of the given slot at the
+     * id.
+     * @param id
+     * @return
+     */
+    public Object getFieldValue(final int index) {
+        return this.values[index];
+    }
+
+    public Object getFieldValue(final String name) {
+        return this.values[this.factTemplate.getFieldTemplateIndex( name )];
+    }
+
+    public void setFieldValue(final String name,
+                              final Object value) {
+        setFieldValue( this.factTemplate.getFieldTemplateIndex( name ),
+                       value );
+    }
+
+    public void setFieldValue(final int index,
+                              final Object value) {
+        this.values[index] = value;
+    }
+
+    /**
+     * Return the long factId
+     */
+    public long getFactId() {
+        return this.id;
+    }
+
+    /**
+     * this is used to reset the id, in the event an user tries to
+     * assert the same fact again, we reset the id to the existing one.
+     * @param fact
+     */
+    protected void resetId(final Fact fact) {
+        this.id = fact.getFactId();
+    }
+
+    /**
+     * Return the deftemplate for the fact
+     */
+    public FactTemplate getFactTemplate() {
+        return this.factTemplate;
+    }
+
+    public int hashCode() {
+        if ( this.hashCode == 0 ) {
+            final int PRIME = 31;
+            int result = 1;
+            result = PRIME * result + this.factTemplate.hashCode();
+            result = PRIME * result + FactImpl.hashCode( this.values );
+            this.hashCode = result;
+
+        }
+        return this.hashCode;
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || FactImpl.class != object.getClass() ) {
+            return false;
+        }
+
+        final FactImpl other = (FactImpl) object;
+
+        if ( !this.factTemplate.equals( other.factTemplate ) ) {
+            return false;
+        }
+
+        if ( !Arrays.equals( this.values,
+                             other.values ) ) {
+            return false;
+        }
+
+        return true;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FactTemplate.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FactTemplate.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FactTemplate.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2002-2005 Peter Lin & RuleML.
+ *
+ * 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://ruleml-dev.sourceforge.net/
+ *
+ * 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.facttemplates;
+
+import java.io.Serializable;
+
+import org.drools.rule.Package;
+
+/**
+ * @author Peter Lin
+ *
+ * Template defines the methods to access an object, which is the
+ * equivalent of un-ordered facts. It defines all the necessary
+ * methods for Deftemplate.
+ */
+public interface FactTemplate
+    extends
+    Serializable {
+
+    Package getPackage();
+
+    /**
+     * The name of the template may be the fully qualified
+     * class name, or an alias.
+     * @return
+     */
+    String getName();
+
+    /**
+     * templates may have 1 or more slots. A slot is a named
+     * pattern with a specific type of value.
+     * @return
+     */
+    int getNumberOfFields();
+
+    /**
+     * Return an array of all the slots.
+     * @return
+     */
+    FieldTemplate[] getAllFieldTemplates();
+
+    /**
+     * Return the slot with the String name
+     * @return
+     */
+    FieldTemplate getFieldTemplate(String name);
+
+    /**
+     * Get the Slot at the given pattern id
+     * @param index
+     * @return
+     */
+    FieldTemplate getFieldTemplate(int index);
+
+    /**
+     * Get the pattern index with the given name
+     * @param name
+     * @return
+     */
+    int getFieldTemplateIndex(String name);
+
+    Fact createFact(long id);
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FactTemplateFieldExtractor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FactTemplateFieldExtractor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FactTemplateFieldExtractor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,99 @@
+package org.drools.facttemplates;
+
+import java.lang.reflect.Method;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.ValueType;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.FieldExtractor;
+import org.drools.util.ClassUtils;
+
+public class FactTemplateFieldExtractor
+    implements
+    FieldExtractor {
+
+    private static final long serialVersionUID = 400L;
+    private FactTemplate      factTemplate;
+    private int               fieldIndex;
+
+    public FactTemplateFieldExtractor(final FactTemplate factTemplate,
+                                      final int fieldIndex) {
+        this.factTemplate = factTemplate;
+        this.fieldIndex = fieldIndex;
+    }
+
+    public ValueType getValueType() {
+        return this.factTemplate.getFieldTemplate( this.fieldIndex ).getValueType();
+    }
+
+    public Object getValue(InternalWorkingMemory workingMemory, final Object object) {
+        return ((Fact) object).getFieldValue( this.fieldIndex );
+    }
+
+    public int getIndex() {
+        return this.fieldIndex;
+    }
+
+    public Class getExtractToClass() {
+        return Fact.class;//this.factTemplate.getFieldTemplate( fieldIndex ).getValueType().getClass();
+    }
+
+    public String getExtractToClassName() {
+        return ClassUtils.canonicalName( Fact.class );//this.factTemplate.getFieldTemplate( fieldIndex ).getValueType().getClass();
+    }
+
+    public boolean getBooleanValue(InternalWorkingMemory workingMemory, final Object object) {
+        return ((Boolean) ((Fact) object).getFieldValue( this.fieldIndex )).booleanValue();
+    }
+
+    public byte getByteValue(InternalWorkingMemory workingMemory, final Object object) {
+        return ((Number) ((Fact) object).getFieldValue( this.fieldIndex )).byteValue();
+    }
+
+    public char getCharValue(InternalWorkingMemory workingMemory, final Object object) {
+        return ((Character) ((Fact) object).getFieldValue( this.fieldIndex )).charValue();
+    }
+
+    public double getDoubleValue(InternalWorkingMemory workingMemory, final Object object) {
+        return ((Number) ((Fact) object).getFieldValue( this.fieldIndex )).doubleValue();
+    }
+
+    public float getFloatValue(InternalWorkingMemory workingMemory, final Object object) {
+        return ((Number) ((Fact) object).getFieldValue( this.fieldIndex )).floatValue();
+    }
+
+    public int getIntValue(InternalWorkingMemory workingMemory, final Object object) {
+        return ((Number) ((Fact) object).getFieldValue( this.fieldIndex )).intValue();
+    }
+
+    public long getLongValue(InternalWorkingMemory workingMemory, final Object object) {
+        return ((Number) ((Fact) object).getFieldValue( this.fieldIndex )).longValue();
+    }
+
+    public short getShortValue(InternalWorkingMemory workingMemory, final Object object) {
+        return ((Number) ((Fact) object).getFieldValue( this.fieldIndex )).shortValue();
+    }
+
+    public Method getNativeReadMethod() {
+        try {
+            return this.getClass().getDeclaredMethod( "getValue",
+                                                      new Class[]{Object.class} );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( "This is a bug. Please report to development team: " + e.getMessage(),
+                                              e );
+        }
+    }
+
+    public int getHashCode(InternalWorkingMemory workingMemory, final Object object) {
+        return getValue( workingMemory, object ).hashCode();
+    }
+
+    public boolean isGlobal() {
+        return false;
+    }
+
+    public boolean isNullValue(InternalWorkingMemory workingMemory,
+                               Object object) {
+        return ((Fact) object).getFieldValue( this.fieldIndex ) == null;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FactTemplateImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FactTemplateImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FactTemplateImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2002-2005 Peter Lin & RuleML.
+ *
+ * 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://ruleml-dev.sourceforge.net/
+ *
+ * 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.facttemplates;
+
+import java.util.Arrays;
+
+import org.drools.rule.Package;
+
+/**
+ * @author Peter Lin
+ * Deftemplate is equivalent to CLIPS deftemplate<br/>
+ * 
+ * Some general design notes about the current implementation. In the
+ * case where a class is declared to create the deftemplate, the order
+ * of the slots are based on java Introspection. In the case where an
+ * user declares the deftemplate from console or directly, the order
+ * is the same as the string equivalent.
+ * The current implementation does not address redeclaring a deftemplate
+ * for a couple of reasons. The primary one is how does it affect the
+ * existing RETE nodes. One possible approach is to always add new slots
+ * to the end of the deftemplate and ignore the explicit order. Another
+ * is to recompute the deftemplate, binds and all nodes. The second
+ * approach is very costly and would make redeclaring a deftemplate
+ * undesirable.
+ */
+public class FactTemplateImpl
+    implements
+    FactTemplate {
+    private static int hashCode(final Object[] array) {
+        final int PRIME = 31;
+        if ( array == null ) {
+            return 0;
+        }
+        int result = 1;
+        for ( int index = 0; index < array.length; index++ ) {
+            result = PRIME * result + (array[index] == null ? 0 : array[index].hashCode());
+        }
+        return result;
+    }
+
+    private FieldTemplate[] fields;
+    private Package         pkg;
+    private String          name;
+
+    public FactTemplateImpl(final Package pkg,
+                            final String name,
+                            final FieldTemplate[] fields) {
+        this.pkg = pkg;
+        this.name = name;
+        this.fields = fields;
+        this.pkg.addFactTemplate( this );
+    }
+
+    public Package getPackage() {
+        return this.pkg;
+    }
+
+    /**
+     * the template name is an alias for an object
+     * @param name
+     */
+    public String getName() {
+        return this.name;
+    }
+
+    /**
+     * Return the number of slots in the deftemplate
+     * @return
+     */
+    public int getNumberOfFields() {
+        return this.fields.length;
+    }
+
+    /**
+     * Return all the slots
+     * @return
+     */
+    public FieldTemplate[] getAllFieldTemplates() {
+        return this.fields;
+    }
+
+    /**
+     * A convienance method for finding the slot matching
+     * the String name.
+     * @param name
+     * @return
+     */
+    public FieldTemplate getFieldTemplate(final String name) {
+        for ( int idx = 0; idx < this.fields.length; idx++ ) {
+            if ( this.fields[idx].getName().equals( name ) ) {
+                return this.fields[idx];
+            }
+        }
+        return null;
+    }
+
+    /**
+     * get the Slot at the given pattern id
+     * @param id
+     * @return
+     */
+    public FieldTemplate getFieldTemplate(final int index) {
+        return this.fields[index];
+    }
+
+    /**
+     * Look up the pattern index of the slot
+     * @param name
+     * @return
+     */
+    public int getFieldTemplateIndex(final String name) {
+        for ( int index = 0; index < this.fields.length; index++ ) {
+            if ( this.fields[index].getName().equals( name ) ) {
+                return index;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Method takes a list of Slots and creates a deffact from it.
+     * @param data
+     * @param id
+     * @return
+     */
+    public Fact createFact(final long id) {
+        return new FactImpl( this,
+                             id );
+    }
+
+    /**
+     * Method will return a string format with the int type code
+     * for the slot type
+     */
+    public String toString() {
+        final StringBuffer buf = new StringBuffer();
+        buf.append( "(" + this.name + " " );
+        //        for (int idx=0; idx < this.slots.length; idx++){
+        //            buf.append("(" + this.slots[idx].getName() + 
+        //                    " (type " + ConversionUtils.getTypeName(
+        //                            this.slots[idx].getValueType()) +
+        //                    ") ) ");
+        //        }
+        //        if (this.clazz != null){
+        //            buf.append("[" + this.clazz.getClassObject().getName() + "] ");
+        //        }
+        buf.append( ")" );
+        return buf.toString();
+    }
+
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + FactTemplateImpl.hashCode( this.fields );
+        result = PRIME * result + this.name.hashCode();
+        result = PRIME * result + this.pkg.hashCode();
+        return result;
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || getClass() != object.getClass() ) {
+            return false;
+        }
+
+        final FactTemplateImpl other = (FactTemplateImpl) object;
+        if ( !Arrays.equals( this.fields,
+                             other.fields ) ) {
+            return false;
+        }
+
+        return this.pkg.equals( other.pkg ) && this.name.equals( other.name );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FactTemplateObjectType.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FactTemplateObjectType.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FactTemplateObjectType.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,149 @@
+package org.drools.facttemplates;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.base.ValueType;
+import org.drools.spi.ObjectType;
+
+/**
+ * Java class semantics <code>ObjectType</code>.
+ * 
+ * @author <a href="mailto:bob at werken.com">bob at werken.com </a>
+ * 
+ * @version $Id: ClassObjectType.java,v 1.5 2005/02/04 02:13:36 mproctor Exp $
+ */
+public class FactTemplateObjectType
+    implements
+    ObjectType {
+    // ------------------------------------------------------------
+    // Instance members
+    // ------------------------------------------------------------
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    /** FieldTemplate. */
+    protected FactTemplate    factTemplate;
+
+    private boolean           isEvent;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+     /**
+     * Construct.
+     * 
+     * @param objectTypeClass
+     *            Java object class.
+     */
+    public FactTemplateObjectType(final FactTemplate factTemplate) {
+        this.factTemplate = factTemplate;
+    }
+
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+
+    /**
+     * Return the Fact Template.
+     * 
+     * @return The Fact Template
+     */
+    public FactTemplate getFactTemplate() {
+        return this.factTemplate;
+    }
+
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // org.drools.spi.ObjectType
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+    /**
+     * Determine if the passed <code>Object</code> belongs to the object type
+     * defined by this <code>objectType</code> instance.
+     * 
+     * @param object
+     *            The <code>Object</code> to test.
+     * 
+     * @return <code>true</code> if the <code>Object</code> matches this
+     *         object type, else <code>false</code>.
+     */
+    public boolean matches(final Object object) {
+        if ( object instanceof Fact ) {
+            return this.factTemplate.equals( ((Fact) object).getFactTemplate() );
+        } else {
+            return false;
+        }
+    }
+
+    public boolean isAssignableFrom(Object object) {
+        return this.factTemplate.equals( object );
+    }
+
+    public boolean isAssignableFrom(ObjectType objectType) {
+        if ( !(objectType instanceof FactTemplateObjectType) ) {
+            return false;
+        } else {
+            return this.factTemplate.equals( ((FactTemplateObjectType) objectType).getFactTemplate() );
+        }
+    }
+
+    public ValueType getValueType() {
+        return ValueType.FACTTEMPLATE_TYPE;
+    }
+
+    public boolean isEvent() {
+        return isEvent;
+    }
+
+    public void setEvent(boolean isEvent) {
+        this.isEvent = isEvent;
+    }
+
+   public String toString() {
+        return "[FactTemplateObjectType "+( this.isEvent ? "event=" : "template=") + this.factTemplate.getName() + "]";
+    }
+
+    /**
+     * Determine if another object is equal to this.
+     * 
+     * @param object
+     *            The object to test.
+     * 
+     * @return <code>true</code> if <code>object</code> is equal to this,
+     *         otherwise <code>false</code>.
+     */
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof FactTemplateObjectType) ) {
+            return false;
+        }
+
+        final FactTemplateObjectType other = (FactTemplateObjectType) object;
+
+        return this.factTemplate.equals( other.factTemplate );
+    }
+
+    public int hashCode() {
+        return this.factTemplate.hashCode();
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FieldTemplate.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FieldTemplate.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FieldTemplate.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,13 @@
+package org.drools.facttemplates;
+
+import org.drools.base.ValueType;
+
+public interface FieldTemplate {
+
+    public abstract int getIndex();
+
+    public abstract String getName();
+
+    public abstract ValueType getValueType();
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FieldTemplateImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FieldTemplateImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/facttemplates/FieldTemplateImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,67 @@
+package org.drools.facttemplates;
+
+import org.drools.base.ValueType;
+
+public class FieldTemplateImpl
+    implements
+    FieldTemplate {
+
+    private static final long serialVersionUID = 400L;
+
+    private final String      name;
+    private final int         index;
+    private final ValueType   valueType;
+
+    public FieldTemplateImpl(final String name,
+                             final int index,
+                             final Class clazz) {
+        this.name = name;
+        this.index = index;
+        this.valueType = ValueType.determineValueType( clazz );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.facttemplates.FieldTemplate#getIndex()
+     */
+    public int getIndex() {
+        return this.index;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.facttemplates.FieldTemplate#getName()
+     */
+    public String getName() {
+        return this.name;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.facttemplates.FieldTemplate#getValueType()
+     */
+    public ValueType getValueType() {
+        return this.valueType;
+    }
+
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + this.index;
+        result = PRIME * result + this.name.hashCode();
+        result = PRIME * result + this.valueType.hashCode();
+        return result;
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || getClass() != object.getClass() ) {
+            return false;
+        }
+
+        final FieldTemplateImpl other = (FieldTemplateImpl) object;
+
+        return this.index == other.index && this.name.equals( other.name ) && this.valueType.equals( other.valueType );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/Objenesis.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/Objenesis.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/Objenesis.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,29 @@
+package org.drools.objenesis;
+
+import org.drools.objenesis.instantiator.ObjectInstantiator;
+
+/**
+ * Common interface to all kind of Objenesis objects
+ * 
+ * @author Henri Tremblay
+ */
+public interface Objenesis {
+
+    /**
+     * Will create a new object without any constructor being called
+     * 
+     * @param clazz Class to instantiate
+     * @return New instance of clazz
+     */
+    Object newInstance(Class clazz);
+
+    /**
+     * Will pick the best instantiator for the provided class. If you need to create a lot of
+     * instances from the same class, it is way more efficient to create them from the same
+     * ObjectInstantiator than calling {@link #newInstance(Class)}.
+     * 
+     * @param clazz Class to instantiate
+     * @return Instantiator dedicated to the class
+     */
+    ObjectInstantiator getInstantiatorOf(Class clazz);
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/ObjenesisBase.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/ObjenesisBase.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/ObjenesisBase.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,85 @@
+package org.drools.objenesis;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.objenesis.instantiator.ObjectInstantiator;
+import org.drools.objenesis.strategy.InstantiatorStrategy;
+
+/**
+ * Base class to extend if you want to have a class providing your own default strategy. Can also be
+ * instantiated directly.
+ * 
+ * @author Henri Tremblay
+ */
+public class ObjenesisBase
+    implements
+    Objenesis {
+
+    /** Strategy used by this Objenesi implementation to create classes */
+    protected final InstantiatorStrategy strategy;
+
+    /** Strategy cache. Key = Class, Value = InstantiatorStrategy */
+    protected Map                        cache;
+
+    /**
+     * Constructor allowing to pick a strategy and using cache
+     * 
+     * @param strategy Strategy to use
+     */
+    public ObjenesisBase(final InstantiatorStrategy strategy) {
+        this( strategy,
+              true );
+    }
+
+    /**
+     * Flexible constructor allowing to pick the strategy and if caching should be used
+     * 
+     * @param strategy Strategy to use
+     * @param useCache If {@link ObjectInstantiator}s should be cached
+     */
+    public ObjenesisBase(final InstantiatorStrategy strategy,
+                         final boolean useCache) {
+        if ( strategy == null ) {
+            throw new IllegalArgumentException( "A strategy can't be null" );
+        }
+        this.strategy = strategy;
+        this.cache = useCache ? new HashMap() : null;
+    }
+
+    public String toString() {
+        return getClass().getName() + " using " + this.strategy.getClass().getName() + (this.cache == null ? " without" : " with") + " caching";
+    }
+
+    /**
+     * Will create a new object without any constructor being called
+     * 
+     * @param clazz Class to instantiate
+     * @return New instance of clazz
+     */
+    public Object newInstance(final Class clazz) {
+        return getInstantiatorOf( clazz ).newInstance();
+    }
+
+    /**
+     * Will pick the best instantiator for the provided class. If you need to create a lot of
+     * instances from the same class, it is way more efficient to create them from the same
+     * ObjectInstantiator than calling {@link #newInstance(Class)}.
+     * 
+     * @param clazz Class to instantiate
+     * @return Instantiator dedicated to the class
+     */
+    public synchronized ObjectInstantiator getInstantiatorOf(final Class clazz) {
+        if ( this.cache == null ) {
+            return this.strategy.newInstantiatorOf( clazz );
+        }
+        ObjectInstantiator instantiator = (ObjectInstantiator) this.cache.get( clazz.getName() );
+        if ( instantiator == null ) {
+            instantiator = this.strategy.newInstantiatorOf( clazz );
+            this.cache.put( clazz.getName(),
+                       instantiator );
+        }
+        return instantiator;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/ObjenesisException.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/ObjenesisException.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/ObjenesisException.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,42 @@
+package org.drools.objenesis;
+
+/**
+ * Exception thrown by Objenesis. It wraps any instantiation exceptions. Note that this exception is
+ * runtime to prevent having to catch it. It will do normal exception wrapping for JDK 1.4 and more
+ * and basic message wrapping for JDK 1.3.
+ * 
+ * @author Henri Tremblay
+ */
+public class ObjenesisException extends RuntimeException {
+
+    private static final boolean jdk14 = (Double.parseDouble( System.getProperty( "java.specification.version" ) ) > 1.3);
+
+    /**
+     * @param msg Error message
+     */
+    public ObjenesisException(final String msg) {
+        super( msg );
+    }
+
+    /**
+     * @param cause Wrapped exception. The message will be the one of the cause.
+     */
+    public ObjenesisException(final Throwable cause) {
+        super( cause == null ? null : cause.toString() );
+        if ( jdk14 ) {
+            initCause( cause );
+        }
+    }
+
+    /**
+     * @param msg Error message
+     * @param cause Wrapped exception
+     */
+    public ObjenesisException(final String msg,
+                              final Throwable cause) {
+        super( msg );
+        if ( jdk14 ) {
+            initCause( cause );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/ObjenesisHelper.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/ObjenesisHelper.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/ObjenesisHelper.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,65 @@
+package org.drools.objenesis;
+
+import java.io.Serializable;
+
+import org.drools.objenesis.instantiator.ObjectInstantiator;
+
+/**
+ * Use Objenesis in a static way. <strong>It is strongly not recommended to use this class.</strong>
+ * 
+ * @author Henri Tremblay
+ */
+public final class ObjenesisHelper {
+
+    private static final Objenesis OBJENESIS_STD        = new ObjenesisStd();
+
+    private static final Objenesis OBJENESIS_SERIALIZER = new ObjenesisSerializer();
+
+    private ObjenesisHelper() {
+    }
+
+    /**
+     * Will create a new object without any constructor being called
+     * 
+     * @param clazz Class to instantiate
+     * @return New instance of clazz
+     */
+    public static final Object newInstance(final Class clazz) {
+        return OBJENESIS_STD.newInstance( clazz );
+    }
+
+    /**
+     * Will create an object just like it's done by ObjectInputStream.readObject (the default
+     * constructor of the first non serializable class will be called)
+     * 
+     * @param clazz Class to instantiate
+     * @return New instance of clazz
+     */
+    public static final Serializable newSerializableInstance(final Class clazz) {
+        return (Serializable) OBJENESIS_SERIALIZER.newInstance( clazz );
+    }
+
+    /**
+     * Will pick the best instantiator for the provided class. If you need to create a lot of
+     * instances from the same class, it is way more efficient to create them from the same
+     * ObjectInstantiator than calling {@link #newInstance(Class)}.
+     * 
+     * @param clazz Class to instantiate
+     * @return Instantiator dedicated to the class
+     */
+    public static final ObjectInstantiator getInstantiatorOf(final Class clazz) {
+        return OBJENESIS_STD.getInstantiatorOf( clazz );
+    }
+
+    /**
+     * Same as {@link #getInstantiatorOf(Class)} but providing an instantiator emulating
+     * ObjectInputStream.readObject behavior.
+     * 
+     * @see #newSerializableInstance(Class)
+     * @param clazz Class to instantiate
+     * @return Instantiator dedicated to the class
+     */
+    public static final ObjectInstantiator getSerializableObjectInstantiatorOf(final Class clazz) {
+        return OBJENESIS_SERIALIZER.getInstantiatorOf( clazz );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/ObjenesisSerializer.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/ObjenesisSerializer.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/ObjenesisSerializer.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,29 @@
+package org.drools.objenesis;
+
+import org.drools.objenesis.strategy.SerializingInstantiatorStrategy;
+
+/**
+ * Objenesis implementation using the {@link SerializingInstantiatorStrategy}.
+ * 
+ * @author Henri Tremblay
+ */
+public class ObjenesisSerializer extends ObjenesisBase {
+
+    /**
+     * Default constructor using the {@link org.drools.objenesis.strategy.SerializingInstantiatorStrategy}
+     */
+    public ObjenesisSerializer() {
+        super( new SerializingInstantiatorStrategy() );
+    }
+
+    /**
+     * Instance using the {@link org.drools.objenesis.strategy.SerializingInstantiatorStrategy} with or without caching
+     * {@link org.drools.objenesis.instantiator.ObjectInstantiator}s
+     * 
+     * @param useCache If {@link org.drools.objenesis.instantiator.ObjectInstantiator}s should be cached
+     */
+    public ObjenesisSerializer(final boolean useCache) {
+        super( new SerializingInstantiatorStrategy(),
+               useCache );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/ObjenesisStd.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/ObjenesisStd.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/ObjenesisStd.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,29 @@
+package org.drools.objenesis;
+
+import org.drools.objenesis.strategy.StdInstantiatorStrategy;
+
+/**
+ * Objenesis implementation using the {@link org.drools.objenesis.strategy.StdInstantiatorStrategy}.
+ * 
+ * @author Henri Tremblay
+ */
+public class ObjenesisStd extends ObjenesisBase {
+
+    /**
+     * Default constructor using the {@link org.drools.objenesis.strategy.StdInstantiatorStrategy}
+     */
+    public ObjenesisStd() {
+        super( new StdInstantiatorStrategy() );
+    }
+
+    /**
+     * Instance using the {@link org.drools.objenesis.strategy.StdInstantiatorStrategy} with or without
+     * caching {@link org.drools.objenesis.instantiator.ObjectInstantiator}s
+     * 
+     * @param useCache If {@link org.drools.objenesis.instantiator.ObjectInstantiator}s should be cached
+     */
+    public ObjenesisStd(final boolean useCache) {
+        super( new StdInstantiatorStrategy(),
+               useCache );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/NullInstantiator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/NullInstantiator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/NullInstantiator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,18 @@
+package org.drools.objenesis.instantiator;
+
+/**
+ * The instantiator that always return a null instance
+ * 
+ * @author Henri Tremblay
+ */
+public class NullInstantiator
+    implements
+    ObjectInstantiator {
+
+    /**
+     * @return Always null
+     */
+    public Object newInstance() {
+        return null;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/ObjectInstantiator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/ObjectInstantiator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/ObjectInstantiator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,16 @@
+package org.drools.objenesis.instantiator;
+
+/**
+ * Instantiates a new object.
+ */
+public interface ObjectInstantiator {
+
+    /**
+     * Returns a new instance of an object. The returned object's class is defined by the
+     * implementation.
+     * 
+     * @return A new instance of an object.
+     */
+    Object newInstance();
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/SerializationInstantiatorHelper.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/SerializationInstantiatorHelper.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/SerializationInstantiatorHelper.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,33 @@
+package org.drools.objenesis.instantiator;
+
+import java.io.Serializable;
+
+/**
+ * Helper for common serialization-compatible instantiation functions
+ * 
+ * @author Leonardo Mesquita
+ */
+public class SerializationInstantiatorHelper {
+
+    /**
+     * Returns the first non-serializable superclass of a given class. According to Java Object
+     * Serialization Specification, objects read from a stream are initialized by calling an
+     * accessible no-arg constructor from the first non-serializable superclass in the object's
+     * hierarchy, allowing the state of non-serializable fields to be correctly initialized.
+     * 
+     * @param type Serializable class for which the first non-serializable superclass is to be found
+     * @return The first non-serializable superclass of 'type'.
+     * @see java.io.Serializable
+     */
+    public static Class getNonSerializableSuperClass(final Class type) {
+        Class result = type;
+        while ( Serializable.class.isAssignableFrom( result ) ) {
+            result = result.getSuperclass();
+            if ( result == null ) {
+                throw new Error( "Bad class hierarchy: No non-serializable parents" );
+            }
+        }
+        return result;
+
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/basic/AccessibleInstantiator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/basic/AccessibleInstantiator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/basic/AccessibleInstantiator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,19 @@
+package org.drools.objenesis.instantiator.basic;
+
+
+/**
+ * Instantiates a class by grabbing the no-args constructor, making it accessible and then calling
+ * Constructor.newInstance(). Although this still requires no-arg constructors, it can call
+ * non-public constructors (if the security manager allows it).
+ * 
+ * @see org.drools.objenesis.instantiator.ObjectInstantiator
+ */
+public class AccessibleInstantiator extends ConstructorInstantiator {
+
+    public AccessibleInstantiator(final Class type) {
+        super( type );
+        if ( this.constructor != null ) {
+            this.constructor.setAccessible( true );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/basic/ConstructorInstantiator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/basic/ConstructorInstantiator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/basic/ConstructorInstantiator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,36 @@
+package org.drools.objenesis.instantiator.basic;
+
+import java.lang.reflect.Constructor;
+
+import org.drools.objenesis.ObjenesisException;
+import org.drools.objenesis.instantiator.ObjectInstantiator;
+
+/**
+ * Instantiates a class by grabbing the no args constructor and calling Constructor.newInstance().
+ * This can deal with default public constructors, but that's about it.
+ * 
+ * @see ObjectInstantiator
+ */
+public class ConstructorInstantiator
+    implements
+    ObjectInstantiator {
+
+    protected Constructor constructor;
+
+    public ConstructorInstantiator(final Class type) {
+        try {
+            this.constructor = type.getDeclaredConstructor( (Class[]) null );
+        } catch ( final Exception e ) {
+            throw new ObjenesisException( e );
+        }
+    }
+
+    public Object newInstance() {
+        try {
+            return this.constructor.newInstance( (Object[]) null );
+        } catch ( final Exception e ) {
+            throw new ObjenesisException( e );
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/basic/NewInstanceInstantiator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/basic/NewInstanceInstantiator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/basic/NewInstanceInstantiator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,30 @@
+package org.drools.objenesis.instantiator.basic;
+
+import org.drools.objenesis.ObjenesisException;
+import org.drools.objenesis.instantiator.ObjectInstantiator;
+
+/**
+ * The simplest instantiator - simply calls Class.newInstance(). This can deal with default public
+ * constructors, but that's about it.
+ * 
+ * @see ObjectInstantiator
+ */
+public class NewInstanceInstantiator
+    implements
+    ObjectInstantiator {
+
+    private final Class type;
+
+    public NewInstanceInstantiator(final Class type) {
+        this.type = type;
+    }
+
+    public Object newInstance() {
+        try {
+            return this.type.newInstance();
+        } catch ( final Exception e ) {
+            throw new ObjenesisException( e );
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/basic/ObjectInputStreamInstantiator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/basic/ObjectInputStreamInstantiator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/basic/ObjectInputStreamInstantiator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,170 @@
+package org.drools.objenesis.instantiator.basic;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamClass;
+import java.io.ObjectStreamConstants;
+import java.io.Serializable;
+
+import org.drools.objenesis.ObjenesisException;
+import org.drools.objenesis.instantiator.ObjectInstantiator;
+
+/**
+ * Instantiates a class by using a dummy input stream that always feeds data for an empty object of
+ * the same kind. NOTE: This instantiator may not work properly if the class being instantiated
+ * defines a "readResolve" method, since it may return objects that have been returned previously
+ * (i.e., there's no guarantee that the returned object is a new one), or even objects from a
+ * completely different class.
+ * 
+ * @author Leonardo Mesquita
+ * @see org.drools.objenesis.instantiator.ObjectInstantiator
+ */
+public class ObjectInputStreamInstantiator
+    implements
+    ObjectInstantiator {
+    private static class MockStream extends InputStream {
+
+        private int                pointer;
+        private byte[]             data;
+        private int                sequence;
+        private static final int[] NEXT = new int[]{1, 2, 2};
+        private byte[][]           buffers;
+
+        private final byte[]       FIRST_DATA;
+        private static byte[]      HEADER;
+        private static byte[]      REPEATING_DATA;
+
+        static {
+            initialize();
+        }
+
+        private static void initialize() {
+            try {
+                ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+                DataOutputStream dout = new DataOutputStream( byteOut );
+                dout.writeShort( ObjectStreamConstants.STREAM_MAGIC );
+                dout.writeShort( ObjectStreamConstants.STREAM_VERSION );
+                HEADER = byteOut.toByteArray();
+
+                byteOut = new ByteArrayOutputStream();
+                dout = new DataOutputStream( byteOut );
+
+                dout.writeByte( ObjectStreamConstants.TC_OBJECT );
+                dout.writeByte( ObjectStreamConstants.TC_REFERENCE );
+                dout.writeInt( ObjectStreamConstants.baseWireHandle );
+                REPEATING_DATA = byteOut.toByteArray();
+            } catch ( final IOException e ) {
+                throw new Error( "IOException: " + e.getMessage() );
+            }
+
+        }
+
+        public MockStream(final Class clazz) {
+            this.pointer = 0;
+            this.sequence = 0;
+            this.data = HEADER;
+
+            // (byte) TC_OBJECT
+            // (byte) TC_CLASSDESC
+            // (short length)
+            // (byte * className.length)
+            // (long)serialVersionUID
+            // (byte) SC_SERIALIZABLE
+            // (short)0 <fields>
+            // TC_ENDBLOCKDATA
+            // TC_NULL
+            final ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+            final DataOutputStream dout = new DataOutputStream( byteOut );
+            try {
+                dout.writeByte( ObjectStreamConstants.TC_OBJECT );
+                dout.writeByte( ObjectStreamConstants.TC_CLASSDESC );
+                dout.writeUTF( clazz.getName() );
+                dout.writeLong( ObjectStreamClass.lookup( clazz ).getSerialVersionUID() );
+                dout.writeByte( ObjectStreamConstants.SC_SERIALIZABLE );
+                dout.writeShort( (short) 0 ); // Zero fields
+                dout.writeByte( ObjectStreamConstants.TC_ENDBLOCKDATA );
+                dout.writeByte( ObjectStreamConstants.TC_NULL );
+            } catch ( final IOException e ) {
+                throw new Error( "IOException: " + e.getMessage() );
+            }
+            this.FIRST_DATA = byteOut.toByteArray();
+            this.buffers = new byte[][]{HEADER, this.FIRST_DATA, REPEATING_DATA};
+        }
+
+        private void advanceBuffer() {
+            this.pointer = 0;
+            this.sequence = NEXT[this.sequence];
+            this.data = this.buffers[this.sequence];
+        }
+
+        public int read() throws IOException {
+            final int result = this.data[this.pointer++];
+            if ( this.pointer >= this.data.length ) {
+                advanceBuffer();
+            }
+
+            return result;
+        }
+
+        public int available() throws IOException {
+            return Integer.MAX_VALUE;
+        }
+
+        public int read(final byte[] b,
+                        int off,
+                        final int len) throws IOException {
+            int left = len;
+            int remaining = this.data.length - this.pointer;
+
+            while ( remaining <= left ) {
+                System.arraycopy( this.data,
+                                  this.pointer,
+                                  b,
+                                  off,
+                                  remaining );
+                off += remaining;
+                left -= remaining;
+                advanceBuffer();
+                remaining = this.data.length - this.pointer;
+            }
+            if ( left > 0 ) {
+                System.arraycopy( this.data,
+                                  this.pointer,
+                                  b,
+                                  off,
+                                  left );
+                this.pointer += left;
+            }
+
+            return len;
+        }
+    }
+
+    private ObjectInputStream inputStream;
+
+    public ObjectInputStreamInstantiator(final Class clazz) {
+        if ( Serializable.class.isAssignableFrom( clazz ) ) {
+            try {
+                this.inputStream = new ObjectInputStream( new MockStream( clazz ) );
+            } catch ( final IOException e ) {
+                throw new Error( "IOException: " + e.getMessage() );
+            }
+        } else {
+            throw new ObjenesisException( new NotSerializableException( clazz + " not serializable" ) );
+        }
+    }
+
+    public Object newInstance() {
+        try {
+            return this.inputStream.readObject();
+        } catch ( final ClassNotFoundException e ) {
+            throw new Error( "ClassNotFoundException: " + e.getMessage() );
+        } catch ( final Exception e ) {
+            throw new ObjenesisException( e );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/basic/ObjectStreamClassInstantiator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/basic/ObjectStreamClassInstantiator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/basic/ObjectStreamClassInstantiator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,55 @@
+package org.drools.objenesis.instantiator.basic;
+
+import java.io.ObjectStreamClass;
+import java.lang.reflect.Method;
+
+import org.drools.objenesis.ObjenesisException;
+import org.drools.objenesis.instantiator.ObjectInstantiator;
+
+/**
+ * Instantiates a class by using reflection to make a call to private method
+ * ObjectStreamClass.newInstance, present in many JVM implementations. This instantiator will create
+ * classes in a way compatible with serialization, calling the first non-serializable superclass'
+ * no-arg constructor.
+ * 
+ * @author Leonardo Mesquita
+ * @see ObjectInstantiator
+ * @see java.io.Serializable
+ */
+public class ObjectStreamClassInstantiator
+    implements
+    ObjectInstantiator {
+
+    private static Method newInstanceMethod;
+
+    private static void initialize() {
+        if ( newInstanceMethod == null ) {
+            try {
+                newInstanceMethod = ObjectStreamClass.class.getDeclaredMethod( "newInstance",
+                                                                               new Class[]{} );
+                newInstanceMethod.setAccessible( true );
+            } catch ( final Exception e ) {
+                throw new ObjenesisException( e );
+            }
+        }
+    }
+
+    private ObjectStreamClass objStreamClass;
+
+    public ObjectStreamClassInstantiator(final Class type) {
+        initialize();
+        this.objStreamClass = ObjectStreamClass.lookup( type );
+    }
+
+    public Object newInstance() {
+
+        try {
+            return newInstanceMethod.invoke( this.objStreamClass,
+                                             new Object[]{} );
+        } catch ( final Exception e ) {
+            throw new ObjenesisException( e );
+        }
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/gcj/GCJInstantiator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/gcj/GCJInstantiator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/gcj/GCJInstantiator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,25 @@
+package org.drools.objenesis.instantiator.gcj;
+
+import org.drools.objenesis.ObjenesisException;
+
+/**
+ * Instantiates a class by making a call to internal GCJ private methods. It is only supposed to
+ * work on GCJ JVMs. This instantiator will not call any constructors.
+ * 
+ * @author Leonardo Mesquita
+ * @see org.drools.objenesis.instantiator.ObjectInstantiator
+ */
+public class GCJInstantiator extends GCJInstantiatorBase {
+    public GCJInstantiator(final Class type) {
+        super( type );
+    }
+
+    public Object newInstance() {
+        try {
+            return newObjectMethod.invoke( dummyStream,
+                                           new Object[]{this.type, Object.class} );
+        } catch ( final Exception e ) {
+            throw new ObjenesisException( e );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/gcj/GCJInstantiatorBase.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/gcj/GCJInstantiatorBase.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/gcj/GCJInstantiatorBase.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,50 @@
+package org.drools.objenesis.instantiator.gcj;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.lang.reflect.Method;
+
+import org.drools.objenesis.ObjenesisException;
+import org.drools.objenesis.instantiator.ObjectInstantiator;
+
+/**
+ * Base class for GCJ-based instantiators. It initializes reflection access to method
+ * ObjectInputStream.newObject, as well as creating a dummy ObjectInputStream to be used as the
+ * "this" argument for the method.
+ * 
+ * @author Leonardo Mesquita
+ */
+public abstract class GCJInstantiatorBase
+    implements
+    ObjectInstantiator {
+    protected static Method            newObjectMethod = null;
+    protected static ObjectInputStream dummyStream;
+
+    private static class DummyStream extends ObjectInputStream {
+        public DummyStream() throws IOException {
+            super();
+        }
+    }
+
+    private static void initialize() {
+        if ( newObjectMethod == null ) {
+            try {
+                newObjectMethod = ObjectInputStream.class.getDeclaredMethod( "newObject",
+                                                                             new Class[]{Class.class, Class.class} );
+                newObjectMethod.setAccessible( true );
+                dummyStream = new DummyStream();
+            } catch ( final Exception e ) {
+                throw new ObjenesisException( e );
+            }
+        }
+    }
+
+    protected final Class type;
+
+    public GCJInstantiatorBase(final Class type) {
+        this.type = type;
+        initialize();
+    }
+
+    public abstract Object newInstance();
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/gcj/GCJSerializationInstantiator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/gcj/GCJSerializationInstantiator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/gcj/GCJSerializationInstantiator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,31 @@
+package org.drools.objenesis.instantiator.gcj;
+
+import org.drools.objenesis.ObjenesisException;
+import org.drools.objenesis.instantiator.SerializationInstantiatorHelper;
+
+/**
+ * Instantiates a class by making a call to internal GCJ private methods. It is only supposed to
+ * work on GCJ JVMs. This instantiator will create classes in a way compatible with serialization,
+ * calling the first non-serializable superclass' no-arg constructor.
+ * 
+ * @author Leonardo Mesquita
+ * @see org.drools.objenesis.instantiator.ObjectInstantiator
+ */
+public class GCJSerializationInstantiator extends GCJInstantiatorBase {
+    private Class superType;
+
+    public GCJSerializationInstantiator(final Class type) {
+        super( type );
+        this.superType = SerializationInstantiatorHelper.getNonSerializableSuperClass( type );
+    }
+
+    public Object newInstance() {
+        try {
+            return newObjectMethod.invoke( dummyStream,
+                                           new Object[]{this.type, this.superType} );
+        } catch ( final Exception e ) {
+            throw new ObjenesisException( e );
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/jrockit/JRockit131Instantiator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/jrockit/JRockit131Instantiator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/jrockit/JRockit131Instantiator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,81 @@
+/**
+ * COPYRIGHT & LICENSE
+ *
+ * This code is Copyright (c) 2006 BEA Systems, inc. It is provided free, as-is and without any warranties for the purpose of
+ * inclusion in Objenesis or any other open source project with a FSF approved license, as long as this notice is not
+ * removed. There are no limitations on modifying or repackaging the code apart from this. 
+ *
+ * BEA does not guarantee that the code works, and provides no support for it. Use at your own risk.
+ *
+ * Originally developed by Leonardo Mesquita. Copyright notice added by Henrik Sthl, BEA JRockit Product Manager.
+ *  
+ */
+package org.drools.objenesis.instantiator.jrockit;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+import org.drools.objenesis.ObjenesisException;
+import org.drools.objenesis.instantiator.ObjectInstantiator;
+
+/**
+ * Instantiates a class by making a call to internal JRockit private methods. It is only supposed to
+ * work on JRockit 7.0 JVMs, which are compatible with Java API 1.3.1. This instantiator will not
+ * call any constructors.
+ * 
+ * @author Leonardo Mesquita
+ * @see org.drools.objenesis.instantiator.ObjectInstantiator
+ */
+public class JRockit131Instantiator
+    implements
+    ObjectInstantiator {
+
+    private Constructor   mungedConstructor;
+
+    private static Method newConstructorForSerializationMethod;
+
+    private static void initialize() {
+        if ( newConstructorForSerializationMethod == null ) {
+            Class cl;
+            try {
+                cl = Class.forName( "COM.jrockit.reflect.MemberAccess" );
+                newConstructorForSerializationMethod = cl.getDeclaredMethod( "newConstructorForSerialization",
+                                                                             new Class[]{Constructor.class, Class.class} );
+                newConstructorForSerializationMethod.setAccessible( true );
+            } catch ( final Exception e ) {
+                throw new ObjenesisException( e );
+            }
+        }
+    }
+
+    public JRockit131Instantiator(final Class type) {
+        initialize();
+
+        if ( newConstructorForSerializationMethod != null ) {
+
+            Constructor javaLangObjectConstructor;
+
+            try {
+                javaLangObjectConstructor = Object.class.getConstructor( (Class[]) null );
+            } catch ( final NoSuchMethodException e ) {
+                throw new Error( "Cannot find constructor for java.lang.Object!" );
+            }
+
+            try {
+                this.mungedConstructor = (Constructor) newConstructorForSerializationMethod.invoke( null,
+                                                                                               new Object[]{javaLangObjectConstructor, type} );
+            } catch ( final Exception e ) {
+                throw new ObjenesisException( e );
+            }
+        }
+
+    }
+
+    public Object newInstance() {
+        try {
+            return this.mungedConstructor.newInstance( (Object[]) null );
+        } catch ( final Exception e ) {
+            throw new ObjenesisException( e );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/jrockit/JRockitLegacyInstantiator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/jrockit/JRockitLegacyInstantiator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/jrockit/JRockitLegacyInstantiator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,65 @@
+/**
+ * COPYRIGHT & LICENSE
+ *
+ * This code is Copyright (c) 2006 BEA Systems, inc. It is provided free, as-is and without any warranties for the purpose of
+ * inclusion in Objenesis or any other open source project with a FSF approved license, as long as this notice is not
+ * removed. There are no limitations on modifying or repackaging the code apart from this. 
+ *
+ * BEA does not guarantee that the code works, and provides no support for it. Use at your own risk.
+ *
+ * Originally developed by Leonardo Mesquita. Copyright notice added by Henrik Sthl, BEA JRockit Product Manager.
+ *  
+ */
+
+package org.drools.objenesis.instantiator.jrockit;
+
+import java.lang.reflect.Method;
+
+import org.drools.objenesis.ObjenesisException;
+import org.drools.objenesis.instantiator.ObjectInstantiator;
+
+/**
+ * Instantiates a class by making a call to internal JRockit private methods. It is only supposed to
+ * work on JRockit 1.4.2 JVMs prior to release R25.1. From release R25.1 on, JRockit supports
+ * sun.reflect.ReflectionFactory, making this "trick" unnecessary. This instantiator will not call
+ * any constructors.
+ * 
+ * @author Leonardo Mesquita
+ * @see org.drools.objenesis.instantiator.ObjectInstantiator
+ * @see org.drools.objenesis.instantiator.sun.SunReflectionFactoryInstantiator
+ */
+public class JRockitLegacyInstantiator
+    implements
+    ObjectInstantiator {
+    private static Method safeAllocObjectMethod = null;
+
+    private static void initialize() {
+        if ( safeAllocObjectMethod == null ) {
+            Class memSystem;
+            try {
+                memSystem = Class.forName( "jrockit.vm.MemSystem" );
+                safeAllocObjectMethod = memSystem.getDeclaredMethod( "safeAllocObject",
+                                                                     new Class[]{Class.class} );
+                safeAllocObjectMethod.setAccessible( true );
+            } catch ( final Exception e ) {
+                throw new ObjenesisException( e );
+            }
+        }
+    }
+
+    private Class type;
+
+    public JRockitLegacyInstantiator(final Class type) {
+        initialize();
+        this.type = type;
+    }
+
+    public Object newInstance() {
+        try {
+            return safeAllocObjectMethod.invoke( null,
+                                                 new Object[]{this.type} );
+        } catch ( final Exception e ) {
+            throw new ObjenesisException( e );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/sun/Sun13Instantiator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/sun/Sun13Instantiator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/sun/Sun13Instantiator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,26 @@
+package org.drools.objenesis.instantiator.sun;
+
+import org.drools.objenesis.ObjenesisException;
+
+/**
+ * Instantiates a class by making a call to internal Sun private methods. It is only supposed to
+ * work on Sun HotSpot 1.3 JVM. This instantiator will not call any constructors.
+ * 
+ * @author Leonardo Mesquita
+ * @see org.drools.objenesis.instantiator.ObjectInstantiator
+ */
+public class Sun13Instantiator extends Sun13InstantiatorBase {
+    public Sun13Instantiator(final Class type) {
+        super( type );
+    }
+
+    public Object newInstance() {
+        try {
+            return allocateNewObjectMethod.invoke( null,
+                                                   new Object[]{this.type, Object.class} );
+        } catch ( final Exception e ) {
+            throw new ObjenesisException( e );
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/sun/Sun13InstantiatorBase.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/sun/Sun13InstantiatorBase.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/sun/Sun13InstantiatorBase.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,41 @@
+package org.drools.objenesis.instantiator.sun;
+
+import java.io.ObjectInputStream;
+import java.lang.reflect.Method;
+
+import org.drools.objenesis.ObjenesisException;
+import org.drools.objenesis.instantiator.ObjectInstantiator;
+
+/**
+ * Base class for Sun 1.3 based instantiators. It initializes reflection access to static method
+ * ObjectInputStream.allocateNewObject.
+ * 
+ * @author Leonardo Mesquita
+ */
+public abstract class Sun13InstantiatorBase
+    implements
+    ObjectInstantiator {
+    protected static Method allocateNewObjectMethod = null;
+
+    private static void initialize() {
+        if ( allocateNewObjectMethod == null ) {
+            try {
+                allocateNewObjectMethod = ObjectInputStream.class.getDeclaredMethod( "allocateNewObject",
+                                                                                     new Class[]{Class.class, Class.class} );
+                allocateNewObjectMethod.setAccessible( true );
+            } catch ( final Exception e ) {
+                throw new ObjenesisException( e );
+            }
+        }
+    }
+
+    protected final Class type;
+
+    public Sun13InstantiatorBase(final Class type) {
+        this.type = type;
+        initialize();
+    }
+
+    public abstract Object newInstance();
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/sun/Sun13SerializationInstantiator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/sun/Sun13SerializationInstantiator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/sun/Sun13SerializationInstantiator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,31 @@
+package org.drools.objenesis.instantiator.sun;
+
+import org.drools.objenesis.ObjenesisException;
+import org.drools.objenesis.instantiator.SerializationInstantiatorHelper;
+
+/**
+ * Instantiates a class by making a call to internal Sun private methods. It is only supposed to
+ * work on Sun HotSpot 1.3 JVM. This instantiator will create classes in a way compatible with
+ * serialization, calling the first non-serializable superclass' no-arg constructor.
+ * 
+ * @author Leonardo Mesquita
+ * @see org.drools.objenesis.instantiator.ObjectInstantiator
+ */
+public class Sun13SerializationInstantiator extends Sun13InstantiatorBase {
+    private final Class superType;
+
+    public Sun13SerializationInstantiator(final Class type) {
+        super( type );
+        this.superType = SerializationInstantiatorHelper.getNonSerializableSuperClass( type );
+    }
+
+    public Object newInstance() {
+        try {
+            return allocateNewObjectMethod.invoke( null,
+                                                   new Object[]{this.type, this.superType} );
+        } catch ( final Exception e ) {
+            throw new ObjenesisException( e );
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/sun/SunReflectionFactoryInstantiator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/sun/SunReflectionFactoryInstantiator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/sun/SunReflectionFactoryInstantiator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,46 @@
+package org.drools.objenesis.instantiator.sun;
+
+import java.lang.reflect.Constructor;
+
+import org.drools.objenesis.ObjenesisException;
+import org.drools.objenesis.instantiator.ObjectInstantiator;
+
+import sun.reflect.ReflectionFactory;
+
+/**
+ * Instantiates an object, WITHOUT calling it's constructor, using internal
+ * sun.reflect.ReflectionFactory - a class only available on JDK's that use Sun's 1.4 (or later)
+ * Java implementation. This is the best way to instantiate an object without any side effects
+ * caused by the constructor - however it is not available on every platform.
+ * 
+ * @see ObjectInstantiator
+ */
+public class SunReflectionFactoryInstantiator
+    implements
+    ObjectInstantiator {
+
+    private final Constructor mungedConstructor;
+
+    public SunReflectionFactoryInstantiator(final Class type) {
+
+        final ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory();
+        Constructor javaLangObjectConstructor;
+
+        try {
+            javaLangObjectConstructor = Object.class.getConstructor( (Class[]) null );
+        } catch ( final NoSuchMethodException e ) {
+            throw new Error( "Cannot find constructor for java.lang.Object!" );
+        }
+        this.mungedConstructor = reflectionFactory.newConstructorForSerialization( type,
+                                                                              javaLangObjectConstructor );
+        this.mungedConstructor.setAccessible( true );
+    }
+
+    public Object newInstance() {
+        try {
+            return this.mungedConstructor.newInstance( (Object[]) null );
+        } catch ( final Exception e ) {
+            throw new ObjenesisException( e );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/sun/SunReflectionFactorySerializationInstantiator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/sun/SunReflectionFactorySerializationInstantiator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/instantiator/sun/SunReflectionFactorySerializationInstantiator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,56 @@
+package org.drools.objenesis.instantiator.sun;
+
+import java.io.NotSerializableException;
+import java.lang.reflect.Constructor;
+
+import org.drools.objenesis.ObjenesisException;
+import org.drools.objenesis.instantiator.ObjectInstantiator;
+import org.drools.objenesis.instantiator.SerializationInstantiatorHelper;
+
+import sun.reflect.ReflectionFactory;
+
+/**
+ * Instantiates an object using internal sun.reflect.ReflectionFactory - a class only available on
+ * JDK's that use Sun's 1.4 (or later) Java implementation. This instantiator will create classes in
+ * a way compatible with serialization, calling the first non-serializable superclass' no-arg
+ * constructor. This is the best way to instantiate an object without any side effects caused by the
+ * constructor - however it is not available on every platform.
+ * 
+ * @see ObjectInstantiator
+ */
+public class SunReflectionFactorySerializationInstantiator
+    implements
+    ObjectInstantiator {
+
+    private final Constructor mungedConstructor;
+
+    public SunReflectionFactorySerializationInstantiator(final Class type) {
+
+        final Class nonSerializableAncestor = SerializationInstantiatorHelper.getNonSerializableSuperClass( type );
+        final ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory();
+        Constructor nonSerializableAncestorConstructor;
+        try {
+            nonSerializableAncestorConstructor = nonSerializableAncestor.getConstructor( (Class[]) null );
+        } catch ( final NoSuchMethodException e ) {
+            /**
+             * @todo (Henri) I think we should throw a NotSerializableException just to put the same
+             *       message a ObjectInputStream. Otherwise, the user won't know if the null returned
+             *       if a "Not serializable", a "No default constructor on ancestor" or a "Exception in
+             *       constructor"
+             */
+            throw new ObjenesisException( new NotSerializableException( type + " has no suitable superclass constructor" ) );
+        }
+
+        this.mungedConstructor = reflectionFactory.newConstructorForSerialization( type,
+                                                                              nonSerializableAncestorConstructor );
+        this.mungedConstructor.setAccessible( true );
+    }
+
+    public Object newInstance() {
+        try {
+            return this.mungedConstructor.newInstance( (Object[]) null );
+        } catch ( final Exception e ) {
+            throw new ObjenesisException( e );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/strategy/BaseInstantiatorStrategy.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/strategy/BaseInstantiatorStrategy.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/strategy/BaseInstantiatorStrategy.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,35 @@
+package org.drools.objenesis.strategy;
+
+/**
+ * Base {@link InstantiatorStrategy} class basically containing helpful constant to sort out JVMs.
+ * 
+ * @author Henri Tremblay
+ */
+public abstract class BaseInstantiatorStrategy
+    implements
+    InstantiatorStrategy {
+
+    /** JVM_NAME prefix for JRockit */
+    protected static final String JROCKIT        = "BEA";
+
+    /** JVM_NAME prefix for GCJ */
+    protected static final String GNU            = "GNU libgcj";
+
+    /** JVM_NAME prefix for Sun Java HotSpot */
+    protected static final String SUN            = "Java HotSpot";
+
+    /** JVM version */
+    protected static final String VM_VERSION     = System.getProperty( "java.runtime.version" );
+
+    /** JVM version */
+    protected static final String VM_INFO        = System.getProperty( "java.vm.info" );
+
+    /** Vendor version */
+    protected static final String VENDOR_VERSION = System.getProperty( "java.vm.version" );
+
+    /** Vendor name */
+    protected static final String VENDOR         = System.getProperty( "java.vm.vendor" );
+
+    /** JVM name */
+    protected static final String JVM_NAME       = System.getProperty( "java.vm.name" );
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/strategy/InstantiatorStrategy.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/strategy/InstantiatorStrategy.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/strategy/InstantiatorStrategy.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,17 @@
+package org.drools.objenesis.strategy;
+
+import org.drools.objenesis.instantiator.ObjectInstantiator;
+
+/**
+ * Defines a strategy to determine the best instantiator for a class.
+ */
+public interface InstantiatorStrategy {
+
+    /**
+     * Create a dedicated instantiator for the given class
+     * 
+     * @param type Class that will be instantiate
+     * @return Dedicated instantiator
+     */
+    ObjectInstantiator newInstantiatorOf(Class type);
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/strategy/SerializingInstantiatorStrategy.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/strategy/SerializingInstantiatorStrategy.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/strategy/SerializingInstantiatorStrategy.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,49 @@
+package org.drools.objenesis.strategy;
+
+import java.io.NotSerializableException;
+import java.io.Serializable;
+
+import org.drools.objenesis.ObjenesisException;
+import org.drools.objenesis.instantiator.ObjectInstantiator;
+import org.drools.objenesis.instantiator.basic.ObjectStreamClassInstantiator;
+import org.drools.objenesis.instantiator.gcj.GCJSerializationInstantiator;
+import org.drools.objenesis.instantiator.sun.Sun13SerializationInstantiator;
+
+/**
+ * Guess the best serializing instantiator for a given class. The returned instantiator will
+ * instantiate classes like the genuine java serialization framework (the constructor of the first
+ * not serializable class will be called). Currently, the selection doesn't depend on the class. It
+ * relies on the
+ * <ul>
+ * <li>JVM version</li>
+ * <li>JVM vendor</li>
+ * <li>JVM vendor version</li>
+ * </ul>
+ * However, instantiators are stateful and so dedicated to their class.
+ * 
+ * @see ObjectInstantiator
+ */
+public class SerializingInstantiatorStrategy extends BaseInstantiatorStrategy {
+
+    /**
+     * Return an {@link ObjectInstantiator} allowing to create instance following the java
+     * serialization framework specifications.
+     * 
+     * @param type Class to instantiate
+     * @return The ObjectInstantiator for the class
+     */
+    public ObjectInstantiator newInstantiatorOf(final Class type) {
+        if ( !Serializable.class.isAssignableFrom( type ) ) {
+            throw new ObjenesisException( new NotSerializableException( type + " not serializable" ) );
+        }
+        if ( JVM_NAME.startsWith( SUN ) ) {
+            if ( VM_VERSION.startsWith( "1.3" ) ) {
+                return new Sun13SerializationInstantiator( type );
+            }
+        } else if ( JVM_NAME.startsWith( GNU ) ) {
+            return new GCJSerializationInstantiator( type );
+        }
+        return new ObjectStreamClassInstantiator( type );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/strategy/StdInstantiatorStrategy.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/strategy/StdInstantiatorStrategy.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/objenesis/strategy/StdInstantiatorStrategy.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,64 @@
+package org.drools.objenesis.strategy;
+
+import org.drools.objenesis.instantiator.ObjectInstantiator;
+import org.drools.objenesis.instantiator.gcj.GCJInstantiator;
+import org.drools.objenesis.instantiator.jrockit.JRockit131Instantiator;
+import org.drools.objenesis.instantiator.jrockit.JRockitLegacyInstantiator;
+import org.drools.objenesis.instantiator.sun.Sun13Instantiator;
+import org.drools.objenesis.instantiator.sun.SunReflectionFactoryInstantiator;
+
+/**
+ * Guess the best instantiator for a given class. The instantiator will instantiate the class
+ * without calling any constructor. Currently, the selection doesn't depend on the class. It relies
+ * on the
+ * <ul>
+ * <li>JVM version</li>
+ * <li>JVM vendor</li>
+ * <li>JVM vendor version</li>
+ * </ul>
+ * However, instantiators are stateful and so dedicated to their class.
+ * 
+ * @see ObjectInstantiator
+ */
+public class StdInstantiatorStrategy extends BaseInstantiatorStrategy {
+
+    /**
+     * Return an {@link ObjectInstantiator} allowing to create instance without any constructor being
+     * called.
+     * 
+     * @param type Class to instantiate
+     * @return The ObjectInstantiator for the class
+     */
+    public ObjectInstantiator newInstantiatorOf(final Class type) {
+
+        if ( JVM_NAME.startsWith( SUN ) ) {
+            if ( VM_VERSION.startsWith( "1.3" ) ) {
+                return new Sun13Instantiator( type );
+            }
+        } else if ( JVM_NAME.startsWith( JROCKIT ) ) {
+            if ( VM_VERSION.startsWith( "1.3" ) ) {
+                return new JRockit131Instantiator( type );
+            } else if ( VM_VERSION.startsWith( "1.4" ) ) {
+                // JRockit vendor version will be RXX where XX is the version
+                // Versions prior to 26 need special handling
+                // From R26 on, java.vm.version starts with R
+                if ( !VENDOR_VERSION.startsWith( "R" ) ) {
+                    // On R25.1 and R25.2, ReflectionFactory should work. Otherwise, we must use the
+                    // Legacy instantiator.
+                    if ( VM_INFO == null || !VM_INFO.startsWith( "R25.1" ) || !VM_INFO.startsWith( "R25.2" ) ) {
+                        return new JRockitLegacyInstantiator( type );
+                    }
+                }
+            }
+        } else if ( JVM_NAME.startsWith( GNU ) ) {
+            return new GCJInstantiator( type );
+        }
+
+        // Fallback instantiator, should work with:
+        // - Java Hotspot version 1.4 and higher
+        // - JRockit 1.4-R26 and higher
+        // - IBM and Hitachi JVMs
+        // ... might works for others so we just give it a try
+        return new SunReflectionFactoryInstantiator( type );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/ParameterDefinition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/ParameterDefinition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/ParameterDefinition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,17 @@
+package org.drools.process.core;
+
+import org.drools.process.core.datatype.DataType;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface ParameterDefinition {
+    
+    String getName();
+    void setName(String name);
+    
+    DataType getType();
+    void setType(DataType type);
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/Process.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/Process.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/Process.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,96 @@
+package org.drools.process.core;
+
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Represents a some process definition.
+ * A process has a name and a unique id.
+ * When a new version of a process is created, the name stays the same,
+ * but the id and the version of the process should be different.
+ * Different types of processes could be defined (like RuleFlow).
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface Process extends VariableScope {
+
+    /**
+     * Sets the id of this process.
+     * The id should uniquely identify this process.
+     * @param id the id of the process
+     */
+    void setId(String id);
+
+    /**
+     * Returns the id of this process.
+     * @return the id of this process
+     */
+    String getId();
+
+    /**
+     * Sets the name of this process.
+     * @param name the name of this process
+     */
+    void setName(String name);
+
+    /**
+     * Returns the name of this process.
+     * If no name is specified, null is returned.
+     * @return the name of this process
+     */
+    String getName();
+
+    /**
+     * Sets the version of this process.
+     * @param version the version of this process
+     */
+    void setVersion(String version);
+
+    /**
+     * Returns the version of this process.
+     * If no version is specified, null is returned.
+     * @return the version of this process
+     */
+    String getVersion();
+
+    /**
+     * Sets the type of this process.
+     * @param type the type of this process
+     */
+    void setType(String type);
+
+    /**
+     * Returns the type of this process.
+     * @return the type of this process
+     */
+    String getType();
+    
+    /**
+     * Sets the package name of this RuleFlow process
+     * 
+     * @param packageName	the package name of this RuleFlow process
+     */
+    void setPackageName(String packageName);
+
+    /**
+     * Returns the package name of this RuleFlow process
+     * 
+     * @return	the package name of this RuleFlow process
+     */
+    String getPackageName();
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/Variable.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/Variable.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/Variable.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,44 @@
+package org.drools.process.core;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.drools.process.core.datatype.DataType;
+
+/**
+ * Represents a global variable used in a RuleFlow.
+ * A variable has a name (should be unique for this process), a datatype
+ * and possibly an initial value.  
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface Variable {
+
+    String getName();
+
+    void setName(String name);
+
+    DataType getType();
+
+    void setType(DataType type);
+
+    Serializable getValue();
+
+    void setValue(Serializable value);
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/VariableScope.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/VariableScope.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/VariableScope.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,34 @@
+package org.drools.process.core;
+
+import java.util.List;
+
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface VariableScope {
+
+    /**
+     * Returns the variables used in this scope
+     * 
+     * @return  a list of variables of this scope
+     */
+    List<Variable> getVariables();
+
+    /**
+     * Returns the names of the variables used in this scope
+     * 
+     * @return  the variable names of this scope
+     */
+    String[] getVariableNames();
+    
+    /**
+     * Sets the variables used in this scope
+     * 
+     * @param variables the variables
+     * @throws IllegalArugmentException if <code>variables</code> is null
+     */
+    void setVariables(List<Variable> variables);
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/Work.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/Work.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/Work.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,19 @@
+package org.drools.process.core;
+
+import java.util.Map;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface Work {
+
+    void setName(String name);
+    String getName();
+    
+    void setParameter(String name, Object value);
+    void setParameters(Map<String, Object> parameters);
+    Object getParameter(String name);
+    Map<String, Object> getParameters();
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/WorkDefinition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/WorkDefinition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/WorkDefinition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,21 @@
+package org.drools.process.core;
+
+import java.util.Set;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface WorkDefinition {
+    
+    String getName();
+    
+    Set<ParameterDefinition> getParameters();
+    String[] getParameterNames();
+    ParameterDefinition getParameter(String name);
+    
+    Set<ParameterDefinition> getResults();
+    String[] getResultNames();
+    ParameterDefinition getResult(String name);
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/WorkDefinitionExtension.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/WorkDefinitionExtension.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/WorkDefinitionExtension.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,15 @@
+package org.drools.process.core;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface WorkDefinitionExtension {
+    
+    String getDisplayName();
+    
+    String getExplanationText();
+    
+    String getIcon();
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/DataType.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/DataType.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/DataType.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,33 @@
+package org.drools.process.core.datatype;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+/**
+ * Abstract representation of a datatype.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface DataType extends Serializable {
+
+    /**
+     * Returns true if the given value is a valid value of this data type.
+     */
+    boolean verifyDataType(Object value);
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/DataTypeFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/DataTypeFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/DataTypeFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,31 @@
+package org.drools.process.core.datatype;
+
+import java.io.Serializable;
+
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * A factory for creating a datatype.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface DataTypeFactory extends Serializable {
+
+    DataType createDataType();
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/InstanceDataTypeFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/InstanceDataTypeFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/InstanceDataTypeFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,55 @@
+package org.drools.process.core.datatype.impl;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.process.core.datatype.DataType;
+import org.drools.process.core.datatype.DataTypeFactory;
+
+/**
+ * A data type factory that always returns the same instance of a given class.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class InstanceDataTypeFactory implements DataTypeFactory {
+
+    private static final long serialVersionUID = 400L;
+    
+    private Class<?> dataTypeClass;
+    private DataType instance;
+
+    public InstanceDataTypeFactory(final Class<?> dataTypeClass) {
+        this.dataTypeClass = dataTypeClass;
+    }
+
+    public DataType createDataType() {
+        if (this.instance == null) {
+            try {
+                this.instance = (DataType) this.dataTypeClass.newInstance();
+            } catch (final IllegalAccessException e) {
+                throw new RuntimeException(
+                        "Could not create data type for class "
+                                + this.dataTypeClass, e);
+            } catch (final InstantiationException e) {
+                throw new RuntimeException(
+                        "Could not create data type for class "
+                                + this.dataTypeClass, e);
+            }
+        }
+        return this.instance;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/NewInstanceDataTypeFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/NewInstanceDataTypeFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/NewInstanceDataTypeFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,49 @@
+package org.drools.process.core.datatype.impl;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.process.core.datatype.DataType;
+import org.drools.process.core.datatype.DataTypeFactory;
+
+/**
+ * A data type factory that always returns a new instance of a given class.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class NewInstanceDataTypeFactory implements DataTypeFactory {
+
+    private static final long serialVersionUID = 400L;
+    
+    private Class<? extends DataType> dataTypeClass;
+
+    public NewInstanceDataTypeFactory(final Class<? extends DataType> dataTypeClass) {
+        this.dataTypeClass = dataTypeClass;
+    }
+
+    public DataType createDataType() {
+        try {
+            return this.dataTypeClass.newInstance();
+        } catch (final IllegalAccessException e) {
+            throw new RuntimeException("Could not create data type for class "
+                    + this.dataTypeClass, e);
+        } catch (final InstantiationException e) {
+            throw new RuntimeException("Could not create data type for class "
+                    + this.dataTypeClass, e);
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/BooleanDataType.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/BooleanDataType.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/BooleanDataType.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,38 @@
+package org.drools.process.core.datatype.impl.type;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.process.core.datatype.DataType;
+
+/**
+ * Representation of a boolean datatype.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public final class BooleanDataType
+    implements
+    DataType {
+
+    private static final long serialVersionUID = 400L;
+
+    public boolean verifyDataType(final Object value) {
+        if ( value instanceof Boolean ) {
+            return true;
+        }
+        return false;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/FloatDataType.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/FloatDataType.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/FloatDataType.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,41 @@
+package org.drools.process.core.datatype.impl.type;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.process.core.datatype.DataType;
+
+/**
+ * Representation of a float datatype.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public final class FloatDataType
+    implements
+    DataType {
+
+    private static final long serialVersionUID = 400L;
+
+    public boolean verifyDataType(final Object value) {
+        if ( value instanceof Float ) {
+            return true;
+        } else if ( value == null ) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/IntegerDataType.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/IntegerDataType.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/IntegerDataType.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,41 @@
+package org.drools.process.core.datatype.impl.type;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.process.core.datatype.DataType;
+
+/**
+ * Representation of an integer datatype.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class IntegerDataType
+    implements
+    DataType {
+
+    private static final long serialVersionUID = 400L;
+
+    public boolean verifyDataType(final Object value) {
+        if ( value instanceof Integer ) {
+            return true;
+        } else if ( value == null ) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/ListDataType.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/ListDataType.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/ListDataType.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,59 @@
+package org.drools.process.core.datatype.impl.type;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+
+import org.drools.process.core.datatype.DataType;
+
+/**
+ * Representation of a list datatype.
+ * All elements in the list must have the same datatype.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class ListDataType implements DataType, Serializable {
+
+    private static final long serialVersionUID = 400L;
+
+    private DataType dataType;
+
+    public void setDataType(final DataType dataType) {
+        this.dataType = dataType;
+    }
+
+    public DataType getDataType() {
+        return this.dataType;
+    }
+
+    public boolean verifyDataType(final Object value) {
+        if (value == null) {
+            return true;
+        }
+        if (value instanceof List) {
+            for (final Iterator<?> it = ((List<?>) value).iterator(); it.hasNext();) {
+                if (!this.dataType.verifyDataType(it.next())) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/StringDataType.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/StringDataType.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/StringDataType.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,41 @@
+package org.drools.process.core.datatype.impl.type;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.process.core.datatype.DataType;
+
+/**
+ * Representation of a string datatype.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class StringDataType
+    implements
+    DataType {
+
+    private static final long serialVersionUID = 400L;
+
+    public boolean verifyDataType(final Object value) {
+        if ( value instanceof String ) {
+            return true;
+        } else if ( value == null ) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/UndefinedDataType.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/UndefinedDataType.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/datatype/impl/type/UndefinedDataType.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,44 @@
+package org.drools.process.core.datatype.impl.type;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.process.core.datatype.DataType;
+
+/**
+ * Representation of an undefined datatype.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public final class UndefinedDataType implements DataType {
+
+    private static final long serialVersionUID = 400L;
+    private static UndefinedDataType instance;
+
+    public static UndefinedDataType getInstance() {
+        if (instance == null) {
+            instance = new UndefinedDataType();
+        }
+        return instance;
+    }
+
+    public boolean verifyDataType(final Object value) {
+        if (value == null) {
+            return true;
+        }
+        return false;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/ParameterDefinitionImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/ParameterDefinitionImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/ParameterDefinitionImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,49 @@
+package org.drools.process.core.impl;
+
+import java.io.Serializable;
+
+import org.drools.process.core.ParameterDefinition;
+import org.drools.process.core.datatype.DataType;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class ParameterDefinitionImpl implements ParameterDefinition, Serializable {
+   
+    private static final long serialVersionUID = 400L;
+   
+    private String name;
+    private DataType type;
+    
+    public ParameterDefinitionImpl(String name, DataType type) {
+        setName(name);
+        setType(type);
+    }
+    
+    public String getName() {
+        return name;
+    }
+    
+    public void setName(String name) {
+        if (name == null) {
+            throw new IllegalArgumentException("Name cannot be null");
+        }
+        this.name = name;
+    }
+    
+    public DataType getType() {
+        return type;
+    }
+    
+    public void setType(DataType type) {
+        if (type == null) {
+            throw new IllegalArgumentException("Data type cannot be null");
+        }
+        this.type = type;
+    }
+    
+    public String toString() {
+        return name;
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/ProcessImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/ProcessImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/ProcessImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,104 @@
+package org.drools.process.core.impl;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.drools.process.core.Process;
+import org.drools.process.core.Variable;
+import org.drools.process.core.VariableScope;
+
+/**
+ * Default implementation of a Process
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class ProcessImpl implements Process, Serializable {
+    
+    private static final long serialVersionUID = 400L;
+
+    private String            id;
+    private String            name;
+    private String            version;
+    private String            type;
+    private String			  packageName;
+    private VariableScope     variableScope = new VariableScopeImpl();
+
+    public void setId(final String id) {
+        this.id = id;
+    }
+
+    public String getId() {
+        return this.id;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public void setVersion(final String version) {
+        this.version = version;
+    }
+
+    public String getVersion() {
+        return this.version;
+    }
+
+    public String getType() {
+        return this.type;
+    }
+
+    public void setType(final String type) {
+        this.type = type;
+    }
+
+	public String getPackageName() {
+		return packageName;
+	}
+
+	public void setPackageName(String packageName) {
+		this.packageName = packageName;
+	}
+
+    public List<Variable> getVariables() {
+        return variableScope.getVariables();
+    }
+
+    public void setVariables(final List<Variable> variables) {
+        variableScope.setVariables(variables);
+    }
+
+    public String[] getVariableNames() {
+        return variableScope.getVariableNames();
+    }
+
+    public boolean equals(final Object o) {
+        if ( o instanceof ProcessImpl ) {
+            return ((ProcessImpl) o).getName().equals( this.name ) && ((ProcessImpl) o).getVersion().equals( this.version );
+        }
+        return false;
+    }
+
+    public int hashCode() {
+        return this.name.hashCode() + 3 * this.version.hashCode();
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/VariableImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/VariableImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/VariableImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,81 @@
+package org.drools.process.core.impl;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.drools.process.core.Variable;
+import org.drools.process.core.datatype.DataType;
+import org.drools.process.core.datatype.impl.type.UndefinedDataType;
+
+/**
+ * Default implementation of a variable.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class VariableImpl implements Variable, Serializable {
+
+    private static final long serialVersionUID = 400L;
+
+    private String            name;
+    private DataType         type;
+    private Serializable      value;
+
+    public VariableImpl() {
+        this.type = UndefinedDataType.getInstance();
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    public DataType getType() {
+        return this.type;
+    }
+
+    public void setType(final DataType type) {
+        if ( type == null ) {
+            throw new IllegalArgumentException( "type is null" );
+        }
+        this.type = type;
+    }
+
+    public Serializable getValue() {
+        return this.value;
+    }
+
+    public void setValue(final Serializable value) {
+        if ( this.type.verifyDataType( value ) ) {
+            this.value = value;
+        } else {
+            final StringBuffer sb = new StringBuffer();
+            sb.append( "Value <" );
+            sb.append( value );
+            sb.append( "> is not valid for datatype: " );
+            sb.append( this.type );
+            throw new IllegalArgumentException( sb.toString() );
+        }
+    }
+
+    public String toString() {
+        return this.name;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/VariableScopeImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/VariableScopeImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/VariableScopeImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,45 @@
+package org.drools.process.core.impl;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.process.core.Variable;
+import org.drools.process.core.VariableScope;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class VariableScopeImpl implements VariableScope, Serializable {
+
+    private static final long serialVersionUID = 400L;
+    
+    private List<Variable> variables;
+    
+    public VariableScopeImpl() {
+        this.variables = new ArrayList<Variable>();
+    }
+
+    public List<Variable> getVariables() {
+        return this.variables;
+    }
+
+    public void setVariables(final List<Variable> variables) {
+        if ( variables == null ) {
+            throw new IllegalArgumentException( "Variables is null" );
+        }
+        this.variables = variables;
+    }
+
+    public String[] getVariableNames() {
+        final String[] result = new String[this.variables.size()];
+        if (this.variables != null) {
+            for ( int i = 0; i < this.variables.size(); i++ ) {
+                result[i] = ((Variable) this.variables.get( i )).getName();
+            }
+        }
+        return result;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/WorkDefinitionExtensionImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/WorkDefinitionExtensionImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/WorkDefinitionExtensionImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,41 @@
+package org.drools.process.core.impl;
+
+import org.drools.process.core.WorkDefinitionExtension;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class WorkDefinitionExtensionImpl extends WorkDefinitionImpl implements WorkDefinitionExtension {
+    
+    private static final long serialVersionUID = 400L;
+    
+    private String displayName;
+    private String explanationText;
+    private String icon;
+    
+    public String getDisplayName() {
+        return displayName;
+    }
+    
+    public void setDisplayName(String displayName) {
+        this.displayName = displayName;
+    }
+
+    public String getExplanationText() {
+        return explanationText;
+    }
+    
+    public void setExplanationText(String explanationText) {
+        this.explanationText = explanationText;
+    }
+
+    public String getIcon() {
+        return icon;
+    }
+    
+    public void setIcon(String icon) {
+        this.icon = icon;
+    }
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/WorkDefinitionImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/WorkDefinitionImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/WorkDefinitionImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,92 @@
+package org.drools.process.core.impl;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.drools.process.core.ParameterDefinition;
+import org.drools.process.core.WorkDefinition;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class WorkDefinitionImpl implements WorkDefinition, Serializable {
+    
+    private static final long serialVersionUID = 400L;
+    
+    private String name;
+    private Map<String, ParameterDefinition> parameters = new HashMap<String, ParameterDefinition>();
+    private Map<String, ParameterDefinition> results = new HashMap<String, ParameterDefinition>();
+
+    public String getName() {
+        return name;
+    }
+    
+    public void setName(String name) {
+        this.name = name;
+    }
+    
+    public Set<ParameterDefinition> getParameters() {
+    	return new HashSet<ParameterDefinition>(parameters.values());        
+    }
+    
+    public void setParameters(Set<ParameterDefinition> parameters) {
+        this.parameters.clear();
+        Iterator<ParameterDefinition> iterator = parameters.iterator();
+        while (iterator.hasNext()) {
+        	addParameter(iterator.next());
+        }        
+    }
+    
+    public void addParameter(ParameterDefinition parameter) {
+    	parameters.put(parameter.getName(), parameter);
+    }
+    
+    public void removeParameter(String name) {
+        parameters.remove(name);
+    }
+    
+    public String[] getParameterNames() {
+        return parameters.keySet().toArray(new String[parameters.size()]);
+    }
+    
+    public ParameterDefinition getParameter(String name) {
+        return parameters.get(name);
+    }
+    
+    public Set<ParameterDefinition> getResults() {
+    	return new HashSet<ParameterDefinition>(results.values());
+    }
+    
+    public void setResults(Set<ParameterDefinition> results) {
+    	this.results.clear();
+        Iterator<ParameterDefinition> it = results.iterator();
+        while (it.hasNext()) {
+        	addResult(it.next());
+        }   
+    }
+    
+    public void addResult(ParameterDefinition result) {
+        results.put(result.getName(), result);
+    }
+    
+    public void removeResult(String name) {
+        results.remove(name);
+    }
+    
+    public String[] getResultNames() {
+        return results.keySet().toArray(new String[results.size()]);
+    }
+    
+    public ParameterDefinition getResult(String name) {
+        return results.get(name);
+    }
+    
+    public String toString() {
+        return name;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/WorkImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/WorkImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/impl/WorkImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,57 @@
+package org.drools.process.core.impl;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.process.core.Work;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class WorkImpl implements Work, Serializable {
+    
+    private static final long serialVersionUID = 400L;
+    
+    private String name;
+    private Map<String, Object> parameters = new HashMap<String, Object>();
+    
+    public void setName(String name) {
+        this.name = name;
+    }
+    
+    public String getName() {
+        return name;
+    }
+    
+    public void setParameter(String name, Object value) {
+    	if (name == null) {
+    		throw new NullPointerException("Parameter name is null");
+    	}
+		parameters.put(name, value);
+    }
+    
+    public void setParameters(Map<String, Object> parameters) {
+        if (parameters == null) {
+            throw new NullPointerException();
+        }
+        this.parameters = new HashMap<String, Object>(parameters);
+    }
+    
+    public Object getParameter(String name) {
+        if (name == null) {
+            throw new NullPointerException("Parameter name is null");
+        }
+        return parameters.get(name);
+    }
+    
+    public Map<String, Object> getParameters() {
+        return Collections.unmodifiableMap(parameters);
+    }
+    
+    public String toString() {
+        return "Work " + name;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/validation/ProcessValidationError.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/validation/ProcessValidationError.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/validation/ProcessValidationError.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,32 @@
+package org.drools.process.core.validation;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.process.core.Process;
+
+/**
+ * Represents a RuleFlow validation error. 
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface ProcessValidationError {
+
+    Process getProcess();
+    
+    String getMessage();
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/validation/ProcessValidator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/validation/ProcessValidator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/validation/ProcessValidator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,30 @@
+package org.drools.process.core.validation;
+
+import org.drools.process.core.Process;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * A validator for validating a RuleFlow process. 
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface ProcessValidator {
+
+    ProcessValidationError[] validateProcess(Process process);
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/validation/impl/ProcessValidationErrorImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/validation/impl/ProcessValidationErrorImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/core/validation/impl/ProcessValidationErrorImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,28 @@
+package org.drools.process.core.validation.impl;
+
+import org.drools.process.core.Process;
+import org.drools.process.core.validation.ProcessValidationError;
+
+public class ProcessValidationErrorImpl implements ProcessValidationError {
+
+    private Process process;
+    private String message;
+    
+    public ProcessValidationErrorImpl(Process process, String message) {
+        this.process = process;
+        this.message = message;
+    }
+    
+    public String getMessage() {
+        return message;
+    }
+
+    public Process getProcess() {
+        return process;
+    }
+    
+    public String toString() {
+        return "Process '" + process.getName() + "' [" + process.getId() + "]: " + getMessage();
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/ProcessInstance.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/ProcessInstance.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/ProcessInstance.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,53 @@
+package org.drools.process.instance;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.common.InternalWorkingMemory;
+import org.drools.process.core.Process;
+
+/**
+ * A process instance is the representation of a process during its execution.
+ * It contains all the runtime status information about the running process.
+ * A process can have multiple instances.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface ProcessInstance extends VariableScopeInstance, WorkItemListener {
+
+    int STATE_PENDING   = 0;
+    int STATE_ACTIVE    = 1;
+    int STATE_COMPLETED = 2;
+    int STATE_ABORTED   = 3;
+    int STATE_SUSPENDED = 4;
+
+    void setId(long id);
+
+    long getId();
+
+    void setProcess(Process process);
+
+    Process getProcess();
+
+    void setState(int state);
+
+    int getState();
+    
+    void setWorkingMemory(InternalWorkingMemory workingMemory);
+    
+    void start();
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/ProcessInstanceFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/ProcessInstanceFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/ProcessInstanceFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,11 @@
+package org.drools.process.instance;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface ProcessInstanceFactory {
+    
+    ProcessInstance createProcessInstance();
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/VariableScopeInstance.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/VariableScopeInstance.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/VariableScopeInstance.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,17 @@
+package org.drools.process.instance;
+
+import java.util.Map;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface VariableScopeInstance {
+
+    Map<String, Object> getVariables();
+    
+    Object getVariable(String name);
+    
+    void setVariable(String name, Object value);
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/WorkItem.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/WorkItem.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/WorkItem.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,30 @@
+package org.drools.process.instance;
+
+import java.util.Map;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface WorkItem {
+	
+	int PENDING = 0;
+	int ACTIVE = 1;
+	int COMPLETED = 2;
+	int ABORTED = 3;
+
+    long getId();
+    
+    String getName();
+    
+    int getState();
+    
+    Object getParameter(String name);
+    Map<String, Object> getParameters();
+    
+    Object getResult(String name);
+    Map<String, Object> getResults();
+
+    long getProcessInstanceId();
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/WorkItemHandler.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/WorkItemHandler.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/WorkItemHandler.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,13 @@
+package org.drools.process.instance;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface WorkItemHandler {
+    
+    void executeWorkItem(WorkItem workItem, WorkItemManager manager);
+    
+    void abortWorkItem(WorkItem workItem, WorkItemManager manager);
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/WorkItemListener.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/WorkItemListener.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/WorkItemListener.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,9 @@
+package org.drools.process.instance;
+
+public interface WorkItemListener {
+
+    void workItemCompleted(WorkItem workItem);
+    
+    void workItemAborted(WorkItem workItem);
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/WorkItemManager.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/WorkItemManager.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/WorkItemManager.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,82 @@
+package org.drools.process.instance;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.drools.WorkingMemory;
+import org.drools.process.instance.impl.WorkItemImpl;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class WorkItemManager implements Serializable {
+
+    private static final long serialVersionUID = 400L;
+    
+    private long workItemCounter; 
+	private Map<Long, WorkItem> workItems = new HashMap<Long, WorkItem>();
+	private WorkingMemory workingMemory;
+	private Map<String, WorkItemHandler> workItemHandlers = new HashMap<String, WorkItemHandler>();
+	
+	public WorkItemManager(WorkingMemory workingMemory) {
+	    this.workingMemory = workingMemory;
+	}
+	
+	public void executeWorkItem(WorkItem workItem) {
+	    ((WorkItemImpl) workItem).setId(++workItemCounter);
+	    workItems.put(new Long(workItem.getId()), workItem);
+	    WorkItemHandler handler = (WorkItemHandler) this.workItemHandlers.get(workItem.getName());
+	    if (handler != null) {
+	        handler.executeWorkItem(workItem, this);
+	    } else {
+	        System.err.println("Could not find work item handler for " + workItem.getName());
+	    }
+	}
+	
+	public Set<WorkItem> getWorkItems() {
+	    return new HashSet<WorkItem>(workItems.values());
+
+	}
+	
+    public void completeWorkItem(long id, Map<String, Object> results) {
+        WorkItemImpl workItem = (WorkItemImpl) workItems.get(new Long(id));
+        if (workItem == null) {
+            throw new IllegalArgumentException(
+                "Could not find work item with id " + id);
+        }
+        workItem.setResults(results);
+        ProcessInstance processInstance = workingMemory.getProcessInstance(workItem.getProcessInstanceId());
+        if (processInstance == null) {
+            throw new IllegalArgumentException(
+                "Could not find processInstance with id " + workItem.getProcessInstanceId());
+        }
+        workItem.setState(WorkItem.COMPLETED);
+        processInstance.workItemCompleted(workItem);
+        workItems.remove(new Long(id));
+    }
+    
+    public void abortWorkItem(long id) {
+        WorkItemImpl workItem = (WorkItemImpl) workItems.get(new Long(id));
+        if (workItem == null) {
+            throw new IllegalArgumentException(
+                "Could not find work item with id " + id);
+        }
+        ProcessInstance processInstance = workingMemory.getProcessInstance(workItem.getProcessInstanceId());
+        if (processInstance == null) {
+            throw new IllegalArgumentException(
+                "Could not find processInstance with id " + workItem.getProcessInstanceId());
+        }
+        workItem.setState(WorkItem.ABORTED);
+        processInstance.workItemAborted(workItem);
+        workItems.remove(new Long(id));
+    }
+    
+    public void registerWorkItemHandler(String workItemName, WorkItemHandler handler) {
+        this.workItemHandlers.put(workItemName, handler);
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/ProcessInstanceImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/ProcessInstanceImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/ProcessInstanceImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,101 @@
+package org.drools.process.instance.impl;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.Map;
+
+import org.drools.process.core.Process;
+import org.drools.process.instance.ProcessInstance;
+import org.drools.process.instance.VariableScopeInstance;
+import org.drools.process.instance.WorkItem;
+
+/**
+ * Default implementation of a process instance.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public abstract class ProcessInstanceImpl implements ProcessInstance, Serializable {
+
+    private long id;
+    private Process process;
+    private int state = STATE_PENDING;
+    private VariableScopeInstance variableScopeInstance = new VariableScopeInstanceImpl();
+
+    public void setId(final long id) {
+        this.id = id;
+    }
+
+    public long getId() {
+        return this.id;
+    }
+
+    public void setProcess(final Process process) {
+        this.process = process;
+    }
+
+    public Process getProcess() {
+        return this.process;
+    }
+
+    public void setState(final int state) {
+        this.state = state;
+    }
+
+    public int getState() {
+        return this.state;
+    }
+    
+    public void workItemCompleted(WorkItem taskInstance) {
+    }
+
+    public void workItemAborted(WorkItem taskInstance) {
+    }
+
+    public Object getVariable(String name) {
+        return variableScopeInstance.getVariable(name);
+    }
+
+    public Map<String, Object> getVariables() {
+        return variableScopeInstance.getVariables();
+    }
+
+    public void setVariable(String name, Object value) {
+        variableScopeInstance.setVariable(name, value);
+    }
+    
+    public void start() {
+        if ( getState() != ProcessInstanceImpl.STATE_PENDING ) {
+            throw new IllegalArgumentException( "A process instance can only be started once" );
+        }
+        setState( ProcessInstanceImpl.STATE_ACTIVE );
+        internalStart();
+    }
+    
+    protected abstract void internalStart();
+
+    public String toString() {
+        final StringBuffer b = new StringBuffer( "ProcessInstance " );
+        b.append( getId() );
+        b.append( " [processId=" );
+        b.append( this.process.getId() );
+        b.append( ",state=" );
+        b.append( this.state );
+        b.append( "]" );
+        return b.toString();
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/VariableScopeInstanceImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/VariableScopeInstanceImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/VariableScopeInstanceImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,36 @@
+package org.drools.process.instance.impl;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.process.instance.VariableScopeInstance;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class VariableScopeInstanceImpl implements VariableScopeInstance, Serializable {
+
+    private static final long serialVersionUID = 400L;
+    
+    private Map<String, Object> variables = new HashMap<String, Object>();
+
+    public Object getVariable(String name) {
+        return variables.get(name);
+    }
+
+    public Map<String, Object> getVariables() {
+        return Collections.unmodifiableMap(variables);
+    }
+
+    public void setVariable(String name, Object value) {
+        if (name == null) {
+            throw new IllegalArgumentException(
+                "The name of a variable may not be null!");
+        }
+        variables.put(name, value);
+    }
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/WorkItemImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/WorkItemImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/WorkItemImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,114 @@
+package org.drools.process.instance.impl;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.drools.process.instance.WorkItem;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class WorkItemImpl implements WorkItem, Serializable {
+
+    private static final long serialVersionUID = 400L;
+    
+    private long id;
+    private String name;
+    private int state = 0;
+    private Map<String, Object> parameters = new HashMap<String, Object>();
+    private Map<String, Object> results = new HashMap<String, Object>();
+    private long processInstanceId;
+    
+    public void setId(long id) {
+        this.id = id;
+    }
+    
+    public long getId() {
+        return id;
+    }
+    
+    public void setName(String name) {
+        this.name = name;
+    }
+    
+    public String getName() {
+        return name;
+    }
+    
+    public void setState(int state) {
+        this.state = state;
+    }
+    
+    public int getState() {
+        return state;
+    }
+    
+    public void setParameters(Map<String, Object> parameters) {
+        for (Iterator<Map.Entry<String, Object>> iterator = parameters.entrySet().iterator(); iterator.hasNext(); ) {
+            Map.Entry<String, Object> entry = iterator.next();
+            setParameter(entry.getKey(), entry.getValue());
+        }
+    }
+    
+    public void setParameter(String name, Object value) {
+        this.parameters.put(name, value);
+    }
+    
+    public Object getParameter(String name) {
+        return parameters.get(name);
+    }
+    
+    public Map<String, Object> getParameters() {
+        return parameters;
+    }
+    
+    public void setResults(Map<String, Object> results) {
+        this.results = results;
+    }
+    
+    public void setResult(String name, Object value) {
+        results.put(name, value);
+    }
+    
+    public Object getResult(String name) {
+        return results.get(name);
+    }
+    
+    public Map<String, Object> getResults() {
+        return results;
+    }
+    
+    public void setProcessInstanceId(long processInstanceId) {
+        this.processInstanceId = processInstanceId;
+    }
+    
+    public long getProcessInstanceId() {
+        return processInstanceId;
+    }
+    
+    public String toString() {
+    	StringBuilder b = new StringBuilder("WorkItem ");
+    	b.append(id);
+    	b.append(" [name=");
+    	b.append(name);
+    	b.append(", state=");
+    	b.append(state);
+    	b.append(", processInstanceId=");
+    	b.append(processInstanceId);
+        b.append(", parameters{");
+    	for (Iterator<Map.Entry<String, Object>> iterator = parameters.entrySet().iterator(); iterator.hasNext(); ) {
+    	    Map.Entry<String, Object> entry = iterator.next();
+    	    b.append(entry.getKey());
+    	    b.append("=");
+    	    b.append(entry.getValue());
+    	    if (iterator.hasNext()) {
+    	        b.append(", ");
+    	    }
+    	}
+        b.append("}]");
+    	return b.toString();
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/demo/DoNothingWorkItemHandler.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/demo/DoNothingWorkItemHandler.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/demo/DoNothingWorkItemHandler.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,19 @@
+package org.drools.process.instance.impl.demo;
+
+import org.drools.process.instance.WorkItem;
+import org.drools.process.instance.WorkItemHandler;
+import org.drools.process.instance.WorkItemManager;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class DoNothingWorkItemHandler implements WorkItemHandler {
+
+    public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
+    }
+
+    public void abortWorkItem(WorkItem workItem, WorkItemManager manager) {
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/demo/SystemOutWorkItemHandler.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/demo/SystemOutWorkItemHandler.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/demo/SystemOutWorkItemHandler.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,23 @@
+package org.drools.process.instance.impl.demo;
+
+import org.drools.process.instance.WorkItem;
+import org.drools.process.instance.WorkItemHandler;
+import org.drools.process.instance.WorkItemManager;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class SystemOutWorkItemHandler implements WorkItemHandler {
+
+    public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
+        System.out.println("Executing work item " + workItem);
+        manager.completeWorkItem(workItem.getId(), null);
+    }
+
+    public void abortWorkItem(WorkItem workItem, WorkItemManager manager) {
+        System.out.println("Aborting work item " + workItem);
+        manager.abortWorkItem(workItem.getId());
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/demo/UIWorkItemHandler.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/demo/UIWorkItemHandler.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/demo/UIWorkItemHandler.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,168 @@
+package org.drools.process.instance.impl.demo;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.ListSelectionModel;
+import javax.swing.WindowConstants;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import org.drools.process.instance.WorkItem;
+import org.drools.process.instance.WorkItemHandler;
+import org.drools.process.instance.WorkItemManager;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class UIWorkItemHandler extends JFrame implements WorkItemHandler {
+
+    private static final long serialVersionUID = 400L;
+    
+    private Map<WorkItem, WorkItemManager> workItems = new HashMap<WorkItem, WorkItemManager>();
+    private JList workItemsList;
+    private JButton selectButton;
+    
+    public UIWorkItemHandler() {
+        setSize(new Dimension(400, 300));
+        setTitle("Work Items");
+        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+        initializeComponent();
+    }
+    
+    private void initializeComponent() {
+        JPanel panel = new JPanel();
+        panel.setLayout(new GridBagLayout());
+        getRootPane().setLayout(new BorderLayout());
+        getRootPane().add(panel, BorderLayout.CENTER);
+        
+        workItemsList = new JList();
+        workItemsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+        workItemsList.addMouseListener(new MouseAdapter() {
+            public void mouseClicked(MouseEvent e) {
+                if (e.getClickCount() == 2) {
+                    select();
+                }
+            }
+        });
+        workItemsList.addListSelectionListener(new ListSelectionListener() {
+            public void valueChanged(ListSelectionEvent e) {
+                selectButton.setEnabled(getSelectedWorkItem() != null);
+            }
+        });
+        reloadWorkItemsList();
+        GridBagConstraints c = new GridBagConstraints();
+        c.weightx = 1;
+        c.weighty = 1;
+        c.fill = GridBagConstraints.BOTH;
+        c.insets = new Insets(5, 5, 5, 5);
+        panel.add(workItemsList, c);
+        
+        selectButton = new JButton("Select");
+        selectButton.setEnabled(false);
+        selectButton.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent event) {
+                select();
+            }
+        });
+        c = new GridBagConstraints();
+        c.gridy = 1;
+        c.weightx = 1;
+        c.anchor = GridBagConstraints.EAST;
+        c.insets = new Insets(5, 5, 5, 5);
+        panel.add(selectButton, c);
+    }
+    
+    private void select() {
+        WorkItem workItem = getSelectedWorkItem();
+        if (workItem != null) {
+            UIWorkItemHandlerDialog dialog = new UIWorkItemHandlerDialog(UIWorkItemHandler.this, workItem);
+            dialog.setVisible(true);
+        }
+    }
+    
+    public WorkItem getSelectedWorkItem() {
+        int index = workItemsList.getSelectedIndex();
+        if (index != -1) {
+            Object selected = workItemsList.getModel().getElementAt(index);
+            if (selected instanceof WorkItemWrapper) {
+                return ((WorkItemWrapper) selected).getWorkItem();
+            }
+        }
+        return null;
+    }
+    
+    private void reloadWorkItemsList() {
+        List<WorkItemWrapper> result = new ArrayList<WorkItemWrapper>();
+        for (Iterator<WorkItem> iterator = workItems.keySet().iterator(); iterator.hasNext(); ) {
+            WorkItem workItem = iterator.next();
+            result.add(new WorkItemWrapper(workItem));
+        }
+        workItemsList.setListData(result.toArray());
+    }
+    
+    public void complete(WorkItem workItem, Map<String, Object> results) {
+        WorkItemManager manager = workItems.get(workItem);
+        if (manager != null) {
+            manager.completeWorkItem(workItem.getId(), results);
+            workItems.remove(workItem);
+            reloadWorkItemsList();
+        }
+        selectButton.setEnabled(getSelectedWorkItem() != null);
+    }
+    
+    public void abort(WorkItem workItem) {
+        WorkItemManager manager = workItems.get(workItem);
+        if (manager != null) {
+            manager.abortWorkItem(workItem.getId());
+            workItems.remove(workItem);
+            reloadWorkItemsList();
+        }
+        selectButton.setEnabled(getSelectedWorkItem() != null);
+    }
+    
+    public void abortWorkItem(WorkItem workItem, WorkItemManager manager) {
+        workItems.remove(workItem);
+        reloadWorkItemsList();
+    }
+
+    public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
+        workItems.put(workItem, manager);
+        reloadWorkItemsList();
+    }
+
+    private class WorkItemWrapper {
+        
+        private WorkItem workItem;
+        
+        public WorkItemWrapper(WorkItem workItem) {
+            this.workItem = workItem;
+        }
+        
+        public WorkItem getWorkItem() {
+            return workItem;
+        }
+        
+        public String toString() {
+            return workItem.getName() + " [" + workItem.getId() + "]";
+        }
+    }
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/demo/UIWorkItemHandlerDialog.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/demo/UIWorkItemHandlerDialog.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/process/instance/impl/demo/UIWorkItemHandlerDialog.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,104 @@
+package org.drools.process.instance.impl.demo;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+
+import org.drools.process.instance.WorkItem;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class UIWorkItemHandlerDialog extends JDialog {
+    
+    private static final long serialVersionUID = 400L;
+    
+    private UIWorkItemHandler handler;
+    private WorkItem workItem;
+    private JButton completeButton;
+    private JButton abortButton;
+    
+    public UIWorkItemHandlerDialog(UIWorkItemHandler handler, WorkItem workItem) {
+        super(handler, "Execute Work Item", true);
+        this.handler = handler;
+        this.workItem = workItem;
+        setSize(new Dimension(400, 300));
+        initializeComponent();
+    }
+
+    private void initializeComponent() {
+        JPanel panel = new JPanel();
+        panel.setLayout(new GridBagLayout());
+        getRootPane().setLayout(new BorderLayout());
+        getRootPane().add(panel, BorderLayout.CENTER);
+        
+        JTextArea params = new JTextArea();
+        params.setText(getParameters());
+        params.setEditable(false);
+        GridBagConstraints c = new GridBagConstraints();
+        c.weightx = 1;
+        c.weighty = 1;
+        c.gridwidth = 2;
+        c.fill = GridBagConstraints.BOTH;
+        c.insets = new Insets(5, 5, 5, 5);
+        panel.add(params, c);
+        
+        completeButton = new JButton("Complete");
+        completeButton.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent event) {
+                complete();
+            }
+        });
+        c = new GridBagConstraints();
+        c.gridy = 1;
+        c.weightx = 1;
+        c.anchor = GridBagConstraints.EAST;
+        c.insets = new Insets(5, 5, 5, 5);
+        panel.add(completeButton, c);
+
+        abortButton = new JButton("Abort");
+        abortButton.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent event) {
+                abort();
+            }
+        });
+        c = new GridBagConstraints();
+        c.gridx = 1;
+        c.gridy = 1;
+        c.insets = new Insets(5, 5, 5, 5);
+        panel.add(abortButton, c);
+    }
+    
+    private String getParameters() {
+        String result = "";
+        if (workItem.getParameters() != null) {
+            for (Iterator<Map.Entry<String, Object>> iterator = workItem.getParameters().entrySet().iterator(); iterator.hasNext(); ) {
+                Map.Entry<String, Object> entry = iterator.next();
+                result += entry.getKey() + " = " + entry.getValue() + "\n";
+            }
+        }
+        return result;
+    }
+    
+    private void complete() {
+        handler.complete(workItem, null);
+        dispose();
+    }
+    
+    private void abort() {
+        handler.abort(workItem);
+        dispose();
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/AccumulateNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/AccumulateNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/AccumulateNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,483 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.reteoo;
+
+import java.util.Arrays;
+
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuntimeDroolsException;
+import org.drools.common.BetaConstraints;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.Accumulate;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.PropagationContext;
+import org.drools.util.ArrayUtils;
+import org.drools.util.Entry;
+import org.drools.util.FactEntry;
+import org.drools.util.Iterator;
+import org.drools.util.ObjectHashMap.ObjectEntry;
+
+/**
+ * AccumulateNode
+ * A beta node capable of doing accumulate logic.
+ *
+ * Created: 04/06/2006
+ * @author <a href="mailto:tirelli at post.com">Edson Tirelli</a> 
+ *
+ * @version $Id: AccumulateNode.java 18163 2008-01-27 21:07:59Z tirelli $
+ */
+public class AccumulateNode extends BetaNode {
+
+    private static final long                serialVersionUID = 400L;
+
+    private final boolean                    unwrapRightObject;
+    private final Accumulate                 accumulate;
+    private final AlphaNodeFieldConstraint[] resultConstraints;
+    private final BetaConstraints            resultBinder;
+
+    public AccumulateNode(final int id,
+                          final TupleSource leftInput,
+                          final ObjectSource rightInput,
+                          final AlphaNodeFieldConstraint[] resultConstraints,
+                          final BetaConstraints sourceBinder,
+                          final BetaConstraints resultBinder,
+                          final Accumulate accumulate,
+                          final boolean unwrapRightObject,
+                          final BuildContext context) {
+        super( id,
+               leftInput,
+               rightInput,
+               sourceBinder );
+        this.resultBinder = resultBinder;
+        this.resultConstraints = resultConstraints;
+        this.accumulate = accumulate;
+        this.unwrapRightObject = unwrapRightObject;
+        this.tupleMemoryEnabled = context.isTupleMemoryEnabled();
+    }
+
+    /**
+     * @inheritDoc
+     * 
+     *  When a new tuple is asserted into an AccumulateNode, do this:
+     *  
+     *  1. Select all matching objects from right memory
+     *  2. Execute the initialization code using the tuple + matching objects
+     *  3. Execute the accumulation code for each combination of tuple+object
+     *  4. Execute the return code
+     *  5. Create a new CalculatedObjectHandle for the resulting object and add it to the tuple
+     *  6. Propagate the tuple
+     *  
+     *  The initialization, accumulation and return codes, in JBRules, are assembled
+     *  into a generated method code and called once for the whole match, as you can see
+     *  bellow:
+     *  
+     *   Object result = this.accumulator.accumulate( ... );
+     *  
+     */
+    public void assertTuple(final ReteTuple leftTuple,
+                            final PropagationContext context,
+                            final InternalWorkingMemory workingMemory) {
+
+        final AccumulateMemory memory = (AccumulateMemory) workingMemory.getNodeMemory( this );
+
+        AccumulateResult accresult = new AccumulateResult();
+
+        if ( this.tupleMemoryEnabled ) {
+            memory.betaMemory.getTupleMemory().add( leftTuple );
+            memory.betaMemory.getCreatedHandles().put( leftTuple,
+                                            accresult,
+                                            false );
+        }
+
+        final Object accContext = this.accumulate.createContext();
+
+        accresult.context = accContext;
+        this.accumulate.init( memory.workingMemoryContext,
+                              accContext,
+                              leftTuple,
+                              workingMemory );
+
+        final Iterator it = memory.betaMemory.getFactHandleMemory().iterator( leftTuple );
+        this.constraints.updateFromTuple( workingMemory,
+                                          leftTuple );
+
+        for ( FactEntry entry = (FactEntry) it.next(); entry != null; entry = (FactEntry) it.next() ) {
+            InternalFactHandle handle = entry.getFactHandle();
+            if ( this.constraints.isAllowedCachedLeft( handle ) ) {
+                if ( this.unwrapRightObject ) {
+                    // if there is a subnetwork, handle must be unwrapped
+                    ReteTuple tuple = (ReteTuple) handle.getObject(); 
+                    handle = tuple.getLastHandle();
+                    this.accumulate.accumulate( memory.workingMemoryContext,
+                                                accContext,
+                                                tuple,
+                                                handle,
+                                                workingMemory );
+                } else {
+                    this.accumulate.accumulate( memory.workingMemoryContext,
+                                                accContext,
+                                                leftTuple,
+                                                handle,
+                                                workingMemory );
+                }
+            }
+        }
+        
+        this.constraints.resetTuple();
+
+        final Object result = this.accumulate.getResult( memory.workingMemoryContext,
+                                                         accContext,
+                                                         leftTuple,
+                                                         workingMemory );
+        
+        if( result == null ) {
+            throw new RuntimeDroolsException("Accumulate must not return a null value.");
+        }
+
+        // First alpha node filters
+        boolean isAllowed = true;
+        final InternalFactHandle handle = workingMemory.getFactHandleFactory().newFactHandle( result, false, workingMemory ); // so far, result is not an event
+
+        for ( int i = 0, length = this.resultConstraints.length; i < length; i++ ) {
+            if ( !this.resultConstraints[i].isAllowed( handle,
+                                                       workingMemory ) ) {
+                isAllowed = false;
+                break;
+            }
+        }
+        if ( isAllowed ) {
+            this.resultBinder.updateFromTuple( workingMemory,
+                                               leftTuple );
+            if ( this.resultBinder.isAllowedCachedLeft( handle ) ) {
+                accresult.handle = handle;
+
+                this.sink.propagateAssertTuple( leftTuple,
+                                                handle,
+                                                context,
+                                                workingMemory );
+            } else {
+                workingMemory.getFactHandleFactory().destroyFactHandle( handle );
+            }
+        } else {
+            workingMemory.getFactHandleFactory().destroyFactHandle( handle );
+        }
+
+    }
+
+    /**
+     * @inheritDoc
+     * 
+     * As the accumulate node will always propagate the tuple,
+     * it must always also retreat it.
+     * 
+     */
+    public void retractTuple(final ReteTuple leftTuple,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+        final AccumulateMemory memory = (AccumulateMemory) workingMemory.getNodeMemory( this );
+        memory.betaMemory.getTupleMemory().remove( leftTuple );
+        final AccumulateResult accresult = (AccumulateResult) memory.betaMemory.getCreatedHandles().remove( leftTuple );
+
+        // if tuple was propagated
+        if ( accresult.handle != null ) {
+            this.sink.propagateRetractTuple( leftTuple,
+                                             accresult.handle,
+                                             context,
+                                             workingMemory );
+
+            // Destroying the acumulate result object 
+            workingMemory.getFactHandleFactory().destroyFactHandle( accresult.handle );
+        }
+
+    }
+
+    /**
+     * @inheritDoc
+     * 
+     *  When a new object is asserted into an AccumulateNode, do this:
+     *  
+     *  1. Select all matching tuples from left memory
+     *  2. For each matching tuple, call a modify tuple
+     *  
+     */
+    public void assertObject(final InternalFactHandle handle,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+
+        final AccumulateMemory memory = (AccumulateMemory) workingMemory.getNodeMemory( this );
+        memory.betaMemory.getFactHandleMemory().add( handle );
+
+        if ( ! this.tupleMemoryEnabled ) {
+            // do nothing here, as we know there are no left tuples at this stage in sequential mode.
+            return;
+        }
+
+        this.constraints.updateFromFactHandle( workingMemory,
+                                               handle );
+
+        // need to clone the tuples to avoid concurrent modification exceptions
+        Entry[] tuples = memory.betaMemory.getTupleMemory().toArray();
+        for ( int i = 0; i < tuples.length; i++ ) {
+            ReteTuple tuple = (ReteTuple) tuples[i];
+            if ( this.constraints.isAllowedCachedRight( tuple ) ) {
+                if ( this.accumulate.supportsReverse() || context.getType() == PropagationContext.ASSERTION ) {
+                    modifyTuple( true,
+                                 tuple,
+                                 handle,
+                                 context,
+                                 workingMemory );
+                } else {
+                    // context is MODIFICATION and does not supports reverse
+                    this.retractTuple( tuple,
+                                       context,
+                                       workingMemory );
+                    this.assertTuple( tuple,
+                                      context,
+                                      workingMemory );
+                }
+            }
+        }
+        
+        this.constraints.resetFactHandle();
+    }
+
+    /**
+     *  @inheritDoc
+     *  
+     *  If an object is retract, call modify tuple for each
+     *  tuple match.
+     */
+    public void retractObject(final InternalFactHandle handle,
+                              final PropagationContext context,
+                              final InternalWorkingMemory workingMemory) {
+        final AccumulateMemory memory = (AccumulateMemory) workingMemory.getNodeMemory( this );
+        if ( !memory.betaMemory.getFactHandleMemory().remove( handle ) ) {
+            return;
+        }
+
+        this.constraints.updateFromFactHandle( workingMemory,
+                                               handle );
+        // need to clone the tuples to avoid concurrent modification exceptions
+        Entry[] tuples = memory.betaMemory.getTupleMemory().toArray();
+        for ( int i = 0; i < tuples.length; i++ ) {
+            ReteTuple tuple = (ReteTuple) tuples[i];
+            if ( this.constraints.isAllowedCachedRight( tuple ) ) {
+                if ( this.accumulate.supportsReverse() ) {
+                    this.modifyTuple( false,
+                                      tuple,
+                                      handle,
+                                      context,
+                                      workingMemory );
+                } else {
+                    this.retractTuple( tuple,
+                                       context,
+                                       workingMemory );
+                    this.assertTuple( tuple,
+                                      context,
+                                      workingMemory );
+                }
+            }
+        }
+        
+        this.constraints.resetFactHandle();
+    }
+
+    public void modifyTuple(final boolean isAssert,
+                            final ReteTuple leftTuple,
+                            InternalFactHandle handle,
+                            final PropagationContext context,
+                            final InternalWorkingMemory workingMemory) {
+
+        final AccumulateMemory memory = (AccumulateMemory) workingMemory.getNodeMemory( this );
+        AccumulateResult accresult = (AccumulateResult) memory.betaMemory.getCreatedHandles().get( leftTuple );
+
+        // if tuple was propagated
+        if ( accresult.handle != null ) {
+            this.sink.propagateRetractTuple( leftTuple,
+                                             accresult.handle,
+                                             context,
+                                             workingMemory );
+
+            // Destroying the acumulate result object 
+            workingMemory.getFactHandleFactory().destroyFactHandle( accresult.handle );
+            accresult.handle = null;
+        }
+
+        ReteTuple tuple = leftTuple;
+        if ( this.unwrapRightObject ) {
+            // if there is a subnetwork, handle must be unwrapped
+            tuple = (ReteTuple) handle.getObject();
+            handle = tuple.getLastHandle();
+        }
+
+        if ( context.getType() == PropagationContext.ASSERTION ) {
+            // assertion
+            if ( accresult.context == null ) {
+                final Object accContext = this.accumulate.createContext();
+
+                this.accumulate.init( memory.workingMemoryContext,
+                                      accContext,
+                                      leftTuple,
+                                      workingMemory );
+
+                accresult.context = accContext;
+            }
+
+            this.accumulate.accumulate( memory.workingMemoryContext,
+                                        accresult.context,
+                                        tuple,
+                                        handle,
+                                        workingMemory );
+        } else if ( context.getType() == PropagationContext.MODIFICATION || 
+                context.getType() == PropagationContext.RULE_ADDITION || 
+                context.getType() == PropagationContext.RULE_REMOVAL ) {
+            // modification
+            if ( isAssert ) {
+                this.accumulate.accumulate( memory.workingMemoryContext,
+                                            accresult.context,
+                                            tuple,
+                                            handle,
+                                            workingMemory );
+            } else {
+                this.accumulate.reverse( memory.workingMemoryContext,
+                                         accresult.context,
+                                         tuple,
+                                         handle,
+                                         workingMemory );
+            }
+        } else {
+            // retraction
+            this.accumulate.reverse( memory.workingMemoryContext,
+                                     accresult.context,
+                                     tuple,
+                                     handle,
+                                     workingMemory );
+        }
+
+        final Object result = this.accumulate.getResult( memory.workingMemoryContext,
+                                                         accresult.context,
+                                                         leftTuple,
+                                                         workingMemory );
+
+        if( result == null ) {
+            throw new RuntimeDroolsException("Accumulate must not return a null value.");
+        }
+
+        // First alpha node filters
+        boolean isAllowed = true;
+        final InternalFactHandle createdHandle = workingMemory.getFactHandleFactory().newFactHandle( result, false, workingMemory ); // so far, result is not an event
+        for ( int i = 0, length = this.resultConstraints.length; i < length; i++ ) {
+            if ( !this.resultConstraints[i].isAllowed( createdHandle,
+                                                       workingMemory ) ) {
+                isAllowed = false;
+                break;
+            }
+        }
+        if ( isAllowed ) {
+            this.resultBinder.updateFromTuple( workingMemory,
+                                               leftTuple );
+            if ( this.resultBinder.isAllowedCachedLeft( createdHandle ) ) {
+                accresult.handle = createdHandle;
+
+                this.sink.propagateAssertTuple( leftTuple,
+                                                createdHandle,
+                                                context,
+                                                workingMemory );
+            } else {
+                workingMemory.getFactHandleFactory().destroyFactHandle( createdHandle );
+            }
+            
+            this.resultBinder.resetTuple();
+        } else {
+            workingMemory.getFactHandleFactory().destroyFactHandle( createdHandle );
+        }
+    }
+
+    public void updateSink(final TupleSink sink,
+                           final PropagationContext context,
+                           final InternalWorkingMemory workingMemory) {
+        final AccumulateMemory memory = (AccumulateMemory) workingMemory.getNodeMemory( this );
+
+        final Iterator it = memory.betaMemory.getCreatedHandles().iterator();
+
+        for ( ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next() ) {
+            AccumulateResult accresult = (AccumulateResult) entry.getValue();
+            sink.assertTuple( new ReteTuple( (ReteTuple) entry.getKey(),
+                                             accresult.handle ),
+                              context,
+                              workingMemory );
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.BaseNode#hashCode()
+     */
+    public int hashCode() {
+        return this.leftInput.hashCode() ^ this.rightInput.hashCode() ^ this.accumulate.hashCode() ^ this.resultBinder.hashCode() ^ ArrayUtils.hashCode( this.resultConstraints );
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof AccumulateNode) ) {
+            return false;
+        }
+
+        final AccumulateNode other = (AccumulateNode) object;
+
+        if ( this.getClass() != other.getClass() || (!this.leftInput.equals( other.leftInput )) || (!this.rightInput.equals( other.rightInput )) || (!this.constraints.equals( other.constraints )) ) {
+            return false;
+        }
+
+        return this.accumulate.equals( other.accumulate ) && resultBinder.equals( other.resultBinder ) && Arrays.equals( this.resultConstraints,
+                                                                                                                         other.resultConstraints );
+    }
+
+    public String toString() {
+        return "[ " + this.getClass().getName() + "(" + this.id + ") ]";
+    }
+
+    /**
+     * Creates a BetaMemory for the BetaNode's memory.
+     */
+    public Object createMemory(final RuleBaseConfiguration config) {
+        AccumulateMemory memory = new AccumulateMemory();
+        memory.betaMemory = this.constraints.createBetaMemory( config );
+        memory.workingMemoryContext = this.accumulate.createWorkingMemoryContext();
+        return memory;
+    }
+
+    public static class AccumulateMemory {
+        private static final long serialVersionUID = 400L;
+        
+        public Object workingMemoryContext;
+        public BetaMemory betaMemory;
+    }
+
+    private static class AccumulateResult {
+        // keeping attributes public just for performance
+        public InternalFactHandle handle;
+        public Object             context;
+    }      
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/AlphaNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/AlphaNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/AlphaNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,342 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import org.drools.FactException;
+import org.drools.RuleBaseConfiguration;
+import org.drools.common.BaseNode;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.NodeMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.PropagationContext;
+import org.drools.util.FactEntry;
+import org.drools.util.FactHashTable;
+import org.drools.util.Iterator;
+
+/**
+ * <code>AlphaNodes</code> are nodes in the <code>Rete</code> network used
+ * to apply <code>FieldConstraint<.code>s on asserted fact 
+ * objects where the <code>FieldConstraint</code>s have no dependencies on any other of the facts in the current <code>Rule</code>.
+ * 
+ *  @see AlphaNodeFieldConstraint
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ *
+ */
+public class AlphaNode extends ObjectSource
+    implements
+    ObjectSinkNode,
+    NodeMemory {
+
+    /**
+     * 
+     */
+    private static final long              serialVersionUID = 400L;
+
+    /** The <code>FieldConstraint</code> */
+    private final AlphaNodeFieldConstraint constraint;
+
+    private ObjectSinkNode                 previousObjectSinkNode;
+    private ObjectSinkNode                 nextObjectSinkNode;
+
+    private boolean                        objectMemoryEnabled;
+
+    private boolean                        objectMemoryAllowed;
+
+    /**
+     * Construct an <code>AlphaNode</code> with a unique id using the provided
+     * <code>FieldConstraint</code> and the given <code>ObjectSource</code>.
+     * Set the boolean flag to true if the node is supposed to have local 
+     * memory, or false otherwise. Memory is optional for <code>AlphaNode</code>s 
+     * and is only of benefic when adding additional <code>Rule</code>s at runtime. 
+     * 
+     * @param id Node's ID
+     * @param constraint Node's constraints
+     * @param objectSource Node's object source
+     * @param hasMemory true if node shall be configured with local memory. False otherwise.
+     */
+    public AlphaNode(final int id,
+                     final AlphaNodeFieldConstraint constraint,
+                     final ObjectSource objectSource,
+                     final BuildContext context) {
+        super( id,
+               objectSource,
+               context.getRuleBase().getConfiguration().getAlphaNodeHashingThreshold() );
+        this.constraint = constraint;
+        this.objectMemoryAllowed = context.isAlphaMemoryAllowed();
+        if ( this.objectMemoryAllowed ) {
+            this.objectMemoryEnabled = context.getRuleBase().getConfiguration().isAlphaMemory();
+        } else {
+            this.objectMemoryEnabled = false;
+        }
+    }
+
+    /**
+     * Retruns the <code>FieldConstraint</code>
+     * 
+     * @return <code>FieldConstraint</code>
+     */
+    public AlphaNodeFieldConstraint getConstraint() {
+        return this.constraint;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.drools.reteoo.BaseNode#attach()
+     */
+    public void attach() {
+        this.objectSource.addObjectSink( this );
+    }
+
+    public void attach(final InternalWorkingMemory[] workingMemories) {
+        attach();
+
+        // we are attaching this node with existing working memories
+        // indicating that we are in a dynamic environment, that might benefit from alpha node memory, if allowed
+        if ( this.objectMemoryAllowed ) {
+            setObjectMemoryEnabled( true );
+        }
+        for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+            final InternalWorkingMemory workingMemory = workingMemories[i];
+            final PropagationContext propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
+                                                                                      PropagationContext.RULE_ADDITION,
+                                                                                      null,
+                                                                                      null );
+            this.objectSource.updateSink( this,
+                                          propagationContext,
+                                          workingMemory );
+        }
+    }
+
+    public void assertObject(final InternalFactHandle handle,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) throws FactException {
+        if ( this.constraint.isAllowed( handle,
+                                        workingMemory ) ) {
+            if ( isObjectMemoryEnabled() ) {
+                final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( this );
+                memory.add( handle,
+                            false );
+            }
+
+            this.sink.propagateAssertObject( handle,
+                                             context,
+                                             workingMemory );
+        }
+    }
+
+    public void retractObject(final InternalFactHandle handle,
+                              final PropagationContext context,
+                              final InternalWorkingMemory workingMemory) {
+        boolean propagate = true;
+        if ( isObjectMemoryEnabled() ) {
+            final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( this );
+            propagate = memory.remove( handle );
+        } else {
+            propagate = this.constraint.isAllowed( handle,
+                                                   workingMemory );
+        }
+        if ( propagate ) {
+            this.sink.propagateRetractObject( handle,
+                                              context,
+                                              workingMemory,
+                                              true );
+        }
+    }
+
+    public void updateSink(final ObjectSink sink,
+                           final PropagationContext context,
+                           final InternalWorkingMemory workingMemory) {
+        FactHashTable memory = null;
+
+        if ( !isObjectMemoryEnabled() ) {
+            // get the objects from the parent
+            ObjectSinkUpdateAdapter adapter = new ObjectSinkUpdateAdapter( sink, this.constraint );
+            this.objectSource.updateSink( adapter,
+                                          context,
+                                          workingMemory );
+        } else {
+            // if already has memory, just iterate and propagate
+            memory = (FactHashTable) workingMemory.getNodeMemory( this );
+            final Iterator it = memory.iterator();
+            for ( FactEntry entry = (FactEntry) it.next(); entry != null; entry = (FactEntry) it.next() ) {
+                sink.assertObject( entry.getFactHandle(),
+                                   context,
+                                   workingMemory );
+            }
+        }
+    }
+
+    public void remove(ReteooBuilder builder,
+                       final BaseNode node, final InternalWorkingMemory[] workingMemories) {
+
+        if ( !node.isInUse() ) {
+            removeObjectSink( (ObjectSink) node );
+        }
+        removeShare(builder);
+        if ( !this.isInUse() ) {
+            for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+                workingMemories[i].clearNodeMemory( this );
+            }
+        }
+        this.objectSource.remove( builder,
+                                  this, workingMemories );
+    }
+
+    public void setObjectMemoryAllowed(boolean objectMemoryAllowed) {
+        this.objectMemoryAllowed = objectMemoryAllowed;
+    }
+
+    public boolean isObjectMemoryEnabled() {
+        return this.objectMemoryEnabled;
+    }
+
+    public void setObjectMemoryEnabled(boolean objectMemoryEnabled) {
+        this.objectMemoryEnabled = objectMemoryEnabled;
+    }
+
+    /**
+     * Creates a HashSet for the AlphaNode's memory.
+     */
+    public Object createMemory(final RuleBaseConfiguration config) {
+        return new FactHashTable();
+    }
+
+    /** 
+     * @inheritDoc
+     */
+    protected void addObjectSink(final ObjectSink objectSink) {
+        super.addObjectSink( objectSink );
+    }
+
+    public String toString() {
+        return "[AlphaNode(" + this.id + ") constraint=" + this.constraint + "]";
+    }
+
+    public int hashCode() {
+        return this.objectSource.hashCode() * 17 + ((this.constraint != null) ? this.constraint.hashCode() : 0);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof AlphaNode) ) {
+            return false;
+        }
+
+        final AlphaNode other = (AlphaNode) object;
+
+        return this.objectSource.equals( other.objectSource ) && this.constraint.equals( other.constraint );
+    }
+
+    /**
+     * Returns the next node
+     * @return
+     *      The next ObjectSinkNode
+     */
+    public ObjectSinkNode getNextObjectSinkNode() {
+        return this.nextObjectSinkNode;
+    }
+
+    /**
+     * Sets the next node 
+     * @param next
+     *      The next ObjectSinkNode
+     */
+    public void setNextObjectSinkNode(final ObjectSinkNode next) {
+        this.nextObjectSinkNode = next;
+    }
+
+    /**
+     * Returns the previous node
+     * @return
+     *      The previous ObjectSinkNode
+     */
+    public ObjectSinkNode getPreviousObjectSinkNode() {
+        return this.previousObjectSinkNode;
+    }
+
+    /**
+     * Sets the previous node 
+     * @param previous
+     *      The previous ObjectSinkNode
+     */
+    public void setPreviousObjectSinkNode(final ObjectSinkNode previous) {
+        this.previousObjectSinkNode = previous;
+    }
+
+    /**
+     * Used with the updateSink method, so that the parent ObjectSource
+     * can  update the  TupleSink
+     * @author mproctor
+     *
+     */
+    private static class ObjectSinkUpdateAdapter
+        implements
+        ObjectSink {
+        private final ObjectSink sink;
+        private final AlphaNodeFieldConstraint constraint;
+
+        public ObjectSinkUpdateAdapter(final ObjectSink sink, 
+                                       final AlphaNodeFieldConstraint constraint ) {
+            this.sink = sink;
+            this.constraint = constraint;
+        }
+
+        public void assertObject(final InternalFactHandle handle,
+                                 final PropagationContext context,
+                                 final InternalWorkingMemory workingMemory) {
+            if ( this.constraint.isAllowed( handle,
+                                            workingMemory ) ) {
+                this.sink.assertObject( handle,
+                                        context,
+                                        workingMemory );
+            }
+        }
+
+        public void modifyObject(final InternalFactHandle handle,
+                                 final PropagationContext context,
+                                 final InternalWorkingMemory workingMemory) {
+            throw new UnsupportedOperationException( "ObjectSinkUpdateAdapter onlys supports assertObject method calls" );
+        }
+
+        public void retractObject(final InternalFactHandle handle,
+                                  final PropagationContext context,
+                                  final InternalWorkingMemory workingMemory) {
+            throw new UnsupportedOperationException( "ObjectSinkUpdateAdapter onlys supports assertObject method calls" );
+        }
+
+        public boolean isObjectMemoryEnabled() {
+            throw new UnsupportedOperationException( "ObjectSinkUpdateAdapter have no Object memory" );
+        }
+
+        public void setObjectMemoryEnabled(boolean objectMemoryEnabled) {
+            throw new UnsupportedOperationException( "ObjectSinkUpdateAdapter have no Object memory" );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/BetaMemory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/BetaMemory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/BetaMemory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,37 @@
+package org.drools.reteoo;
+
+import java.io.Serializable;
+
+import org.drools.util.ObjectHashMap;
+
+public class BetaMemory
+    implements
+    Serializable {
+
+    private static final long serialVersionUID = 400L;
+
+    private TupleMemory       tupleMemory;
+    private FactHandleMemory  factHandleMemory;
+    private ObjectHashMap     createdHandles;
+
+    public BetaMemory(final TupleMemory tupleMemory,
+                      final FactHandleMemory objectMemory) {
+        this.tupleMemory = tupleMemory;
+        this.factHandleMemory = objectMemory;
+    }
+
+    public FactHandleMemory getFactHandleMemory() {
+        return this.factHandleMemory;
+    }
+
+    public TupleMemory getTupleMemory() {
+        return this.tupleMemory;
+    }
+
+    public ObjectHashMap getCreatedHandles() {
+        if ( this.createdHandles == null ) {
+            this.createdHandles = new ObjectHashMap();
+        }
+        return this.createdHandles;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/BetaNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/BetaNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/BetaNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,305 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.RuleBaseConfiguration;
+import org.drools.common.BaseNode;
+import org.drools.common.BetaConstraints;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.NodeMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.spi.PropagationContext;
+import org.drools.util.LinkedList;
+import org.drools.util.LinkedListEntry;
+
+/**
+ * <code>BetaNode</code> provides the base abstract class for <code>JoinNode</code> and <code>NotNode</code>. It implements
+ * both TupleSink and ObjectSink and as such can receive <code>Tuple</code>s and <code>FactHandle</code>s. BetaNode uses BetaMemory
+ * to store the propagated instances.
+ * 
+ * @see org.drools.reteoo.TupleSource
+ * @see org.drools.reteoo.TupleSink
+ * @see org.drools.reteoo.BetaMemory
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ */
+abstract class BetaNode extends TupleSource
+    implements
+    TupleSinkNode,
+    ObjectSinkNode,
+    NodeMemory {
+    // ------------------------------------------------------------
+    // Instance members
+    // ------------------------------------------------------------
+
+    /** The left input <code>TupleSource</code>. */
+    protected final TupleSource     leftInput;
+
+    /** The right input <code>TupleSource</code>. */
+    protected final ObjectSource    rightInput;
+
+    protected final BetaConstraints constraints;
+
+    private TupleSinkNode           previousTupleSinkNode;
+    private TupleSinkNode           nextTupleSinkNode;
+
+    private ObjectSinkNode          previousObjectSinkNode;
+    private ObjectSinkNode          nextObjectSinkNode;
+    
+    protected boolean               objectMemory = true; // hard coded to true
+    protected boolean               tupleMemoryEnabled;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    /**
+     * Constructs a <code>BetaNode</code> using the specified <code>BetaNodeBinder</code>.
+     * 
+     * @param leftInput
+     *            The left input <code>TupleSource</code>.
+     * @param rightInput
+     *            The right input <code>ObjectSource</code>.
+     */
+    BetaNode(final int id,
+             final TupleSource leftInput,
+             final ObjectSource rightInput,
+             final BetaConstraints constraints) {
+        super( id );
+        this.leftInput = leftInput;
+        this.rightInput = rightInput;
+        this.constraints = constraints;
+
+        if ( this.constraints == null ) {
+            throw new RuntimeException( "cannot have null constraints, must at least be an instance of EmptyBetaConstraints" );
+        }
+    }
+
+    public BetaNodeFieldConstraint[] getConstraints() {
+        final LinkedList constraints = this.constraints.getConstraints();
+
+        final BetaNodeFieldConstraint[] array = new BetaNodeFieldConstraint[constraints.size()];
+        int i = 0;
+        for ( LinkedListEntry entry = (LinkedListEntry) constraints.getFirst(); entry != null; entry = (LinkedListEntry) entry.getNext() ) {
+            array[i++] = (BetaNodeFieldConstraint) entry.getObject();
+        }
+        return array;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.BaseNode#attach()
+     */
+    public void attach() {
+        this.leftInput.addTupleSink( this );
+        this.rightInput.addObjectSink( this );
+    }
+
+    public List getRules() {
+        final List list = new ArrayList();
+
+        final TupleSink[] sinks = this.sink.getSinks();
+        for ( int i = 0, length = sinks.length; i < length; i++ ) {
+            if ( sinks[i] instanceof RuleTerminalNode ) {
+                list.add( ((RuleTerminalNode) sinks[i]).getRule().getName() );
+            } else if ( sinks[i] instanceof BetaNode ) {
+                list.addAll( ((BetaNode) sinks[i]).getRules() );
+            }
+        }
+
+        return list;
+    }
+
+    public ObjectTypeNode getObjectTypeNode() {
+        ObjectSource source = this.rightInput;
+        while ( !(source instanceof ObjectTypeNode) ) {
+            source = source.objectSource;
+        }
+        return ((ObjectTypeNode) source);
+    }
+
+    public void attach(final InternalWorkingMemory[] workingMemories) {
+        attach();
+
+        for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+            final InternalWorkingMemory workingMemory = workingMemories[i];
+            final PropagationContext propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
+                                                                                      PropagationContext.RULE_ADDITION,
+                                                                                      null,
+                                                                                      null );
+            this.leftInput.updateSink( this,
+                                       propagationContext,
+                                       workingMemory );
+            this.rightInput.updateSink( this,
+                                        propagationContext,
+                                        workingMemory );
+        }
+
+    }
+
+    public void remove(ReteooBuilder builder,
+                       final BaseNode node, final InternalWorkingMemory[] workingMemories) {
+        if ( !node.isInUse() ) {
+            removeTupleSink( (TupleSink) node );
+        }
+        removeShare(builder);
+
+        if ( !this.isInUse() ) {
+            for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+                workingMemories[i].clearNodeMemory( this );
+            }
+        }
+        this.rightInput.remove( builder,
+                                this, workingMemories );
+        this.leftInput.remove( builder,
+                               this, workingMemories );
+
+    }
+
+    public boolean isObjectMemoryEnabled() {
+        return objectMemory;
+    }
+
+    public void setObjectMemoryEnabled(boolean objectMemory) {
+        this.objectMemory = objectMemory;
+    }
+    
+    public boolean isTupleMemoryEnabled() {
+        return tupleMemoryEnabled;
+    }
+
+    public void setTupleMemoryEnabled(boolean tupleMemoryEnabled) {
+        this.tupleMemoryEnabled = tupleMemoryEnabled;
+    }       
+
+    public String toString() {
+        return "";
+    }
+
+    public void dumpMemory(final InternalWorkingMemory workingMemory) {
+        final MemoryVisitor visitor = new MemoryVisitor( workingMemory );
+        visitor.visit( this );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.BaseNode#hashCode()
+     */
+    public int hashCode() {
+        return this.leftInput.hashCode() ^ this.rightInput.hashCode();
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof BetaNode) ) {
+            return false;
+        }
+
+        final BetaNode other = (BetaNode) object;
+
+        return this.getClass() == other.getClass() && this.leftInput.equals( other.leftInput ) && this.rightInput.equals( other.rightInput ) && this.constraints.equals( other.constraints );
+    }
+
+    /**
+     * Creates a BetaMemory for the BetaNode's memory.
+     */
+    public Object createMemory(final RuleBaseConfiguration config) {
+        return this.constraints.createBetaMemory(config);
+    }
+
+    /**
+     * Returns the next node
+     * @return
+     *      The next TupleSinkNode
+     */
+    public TupleSinkNode getNextTupleSinkNode() {
+        return this.nextTupleSinkNode;
+    }
+
+    /**
+     * Sets the next node 
+     * @param next
+     *      The next TupleSinkNode
+     */
+    public void setNextTupleSinkNode(final TupleSinkNode next) {
+        this.nextTupleSinkNode = next;
+    }
+
+    /**
+     * Returns the previous node
+     * @return
+     *      The previous TupleSinkNode
+     */
+    public TupleSinkNode getPreviousTupleSinkNode() {
+        return this.previousTupleSinkNode;
+    }
+
+    /**
+     * Sets the previous node 
+     * @param previous
+     *      The previous TupleSinkNode
+     */
+    public void setPreviousTupleSinkNode(final TupleSinkNode previous) {
+        this.previousTupleSinkNode = previous;
+    }
+
+    /**
+     * Returns the next node
+     * @return
+     *      The next ObjectSinkNode
+     */
+    public ObjectSinkNode getNextObjectSinkNode() {
+        return this.nextObjectSinkNode;
+    }
+
+    /**
+     * Sets the next node 
+     * @param next
+     *      The next ObjectSinkNode
+     */
+    public void setNextObjectSinkNode(final ObjectSinkNode next) {
+        this.nextObjectSinkNode = next;
+    }
+
+    /**
+     * Returns the previous node
+     * @return
+     *      The previous ObjectSinkNode
+     */
+    public ObjectSinkNode getPreviousObjectSinkNode() {
+        return this.previousObjectSinkNode;
+    }
+
+    /**
+     * Sets the previous node 
+     * @param previous
+     *      The previous ObjectSinkNode
+     */
+    public void setPreviousObjectSinkNode(final ObjectSinkNode previous) {
+        this.previousObjectSinkNode = previous;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ClassObjectTypeConf.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ClassObjectTypeConf.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ClassObjectTypeConf.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,301 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Nov 26, 2007
+ */
+package org.drools.reteoo;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.FactException;
+import org.drools.RuntimeDroolsException;
+import org.drools.base.ClassObjectType;
+import org.drools.base.DroolsQuery;
+import org.drools.base.ShadowProxy;
+import org.drools.base.ShadowProxyFactory;
+import org.drools.common.DroolsObjectInputStream;
+import org.drools.common.InternalRuleBase;
+import org.drools.objenesis.instantiator.ObjectInstantiator;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.reteoo.builder.PatternBuilder;
+import org.drools.rule.EntryPoint;
+import org.drools.rule.TypeDeclaration;
+import org.drools.spi.ObjectType;
+
+public class ClassObjectTypeConf
+    implements
+    ObjectTypeConf,
+    Serializable {
+
+    private static final long serialVersionUID = 8218802585428841926L;
+    
+    private final Class<?>                 cls;
+    private transient InternalRuleBase     ruleBase;
+    private ObjectTypeNode[]               objectTypeNodes;
+
+    protected boolean                      shadowEnabled;
+    protected Class<ShadowProxy>           shadowClass;
+    protected transient ObjectInstantiator instantiator;
+
+    private ObjectTypeNode                 concreteObjectTypeNode;
+    private EntryPoint                     entryPoint;
+
+    public ClassObjectTypeConf(final EntryPoint entryPoint,
+                               final Class<?> clazz,
+                               final InternalRuleBase ruleBase) {
+        this.cls = clazz;
+        this.ruleBase = ruleBase;
+        this.entryPoint = entryPoint;
+        TypeDeclaration type = ruleBase.getTypeDeclaration( clazz );
+        final boolean isEvent = type != null && type.getRole() == TypeDeclaration.Role.EVENT; 
+
+        ObjectType objectType = new ClassObjectType( clazz,
+                                                     isEvent );
+        this.concreteObjectTypeNode = (ObjectTypeNode) ruleBase.getRete().getObjectTypeNodes( entryPoint ).get( objectType );
+        if ( this.concreteObjectTypeNode == null ) {
+            BuildContext context = new BuildContext( ruleBase,
+                                                     ((ReteooRuleBase) ruleBase.getRete().getRuleBase()).getReteooBuilder().getIdGenerator() );
+            context.setCurrentEntryPoint( entryPoint );
+            if ( DroolsQuery.class == clazz ) {
+                context.setTupleMemoryEnabled( false );
+                context.setObjectTypeNodeMemoryEnabled( false );
+                context.setTerminalNodeMemoryEnabled( false );
+            } else if ( context.getRuleBase().getConfiguration().isSequential() ) {
+                // We are in sequential mode, so no nodes should have memory
+                context.setTupleMemoryEnabled( false );
+                context.setObjectTypeNodeMemoryEnabled( false );
+                context.setTerminalNodeMemoryEnabled( false );
+            } else {
+                context.setTupleMemoryEnabled( true );
+                context.setObjectTypeNodeMemoryEnabled( true );
+                context.setTerminalNodeMemoryEnabled( true );
+            }
+            // there must exist an ObjectTypeNode for this concrete class
+            this.concreteObjectTypeNode = PatternBuilder.attachObjectTypeNode( context,
+                                                                               objectType );
+        }
+
+        defineShadowProxyData( clazz );
+    }
+
+    public boolean isAssignableFrom(Object object) {
+        return this.cls.isAssignableFrom( (Class) object );
+    }
+
+    public ObjectTypeNode getConcreteObjectTypeNode() {
+        return this.concreteObjectTypeNode;
+    }
+
+    private void defineShadowProxyData(Class clazz) {
+        Rete rete = this.ruleBase.getRete();
+
+        if ( !ruleBase.getConfiguration().isShadowProxy() || clazz == null || !ruleBase.getConfiguration().isShadowed( clazz.getName() ) ) {
+            this.shadowEnabled = false;
+            this.shadowClass = null;
+            this.instantiator = null;
+            return;
+        }
+
+        //String pkgName = (pkg != null) ? pkg.getName() : "";
+        String pkgName = getPackageName( clazz,
+                                         clazz.getPackage() );
+        if ( "org.drools.reteoo".equals( pkgName ) || "org.drools.base".equals( pkgName ) ) {
+            // We don't shadow internal classes
+            this.shadowEnabled = false;
+            this.shadowClass = null;
+            this.instantiator = null;
+            return;
+        }
+
+        // try to generate proxy for the actual class
+        Class shadowClass = loadOrGenerateProxy( clazz,
+                                                 rete );
+
+        if ( shadowClass == null ) {
+            // if it failed, try to find a parent class
+            ObjectTypeNode[] nodes = this.getMatchingObjectTypes( clazz );
+            Class shadowClassRoot = clazz;
+            while ( shadowClass == null && (shadowClassRoot = this.findAFeasibleSuperclassOrInterface( nodes,
+                                                                                                       shadowClassRoot )) != null ) {
+                shadowClass = loadOrGenerateProxy( shadowClassRoot,
+                                                   rete );
+            }
+        }
+
+        if ( shadowClass != null ) {
+            this.shadowClass = shadowClass;
+            this.shadowEnabled = true;
+            setInstantiator();
+        }
+    }
+
+    /**
+     * This will return the package name - if the package is null, it will
+     * work it out from the class name (this is in cases where funky classloading is used).
+     */
+    public static String getPackageName(Class<?> clazz,
+                                        Package pkg) {
+        String pkgName = "";
+        if ( pkg == null ) {
+            int index = clazz.getName().lastIndexOf( '.' );
+            if ( index != -1 ) pkgName = clazz.getName().substring( 0,
+                                                                    index );
+        } else {
+            pkgName = pkg.getName();
+        }
+        return pkgName;
+
+    }
+
+    private Class loadOrGenerateProxy(Class clazz,
+                                      Rete rete) {
+        Class shadowClass = null;
+        final String shadowProxyName = ShadowProxyFactory.getProxyClassNameForClass( clazz );
+        try {
+            // if already loaded
+            shadowClass = rete.getRuleBase().getMapBackedClassLoader().loadClass( shadowProxyName );
+        } catch ( final ClassNotFoundException cnfe ) {
+            // otherwise, create and load
+            final byte[] proxyBytes = ShadowProxyFactory.getProxyBytes( clazz );
+            if ( proxyBytes != null ) {
+                rete.getRuleBase().getMapBackedClassLoader().addClass( shadowProxyName,
+                                                                       proxyBytes );
+                try {
+                    shadowClass = rete.getRuleBase().getMapBackedClassLoader().loadClass( shadowProxyName );
+                } catch ( ClassNotFoundException e ) {
+                    throw new RuntimeException( "Unable to find or generate the ShadowProxy implementation for '" + clazz + "'" );
+                }
+            }
+
+        }
+        return shadowClass;
+    }
+
+    private Class findAFeasibleSuperclassOrInterface(ObjectTypeNode[] nodes,
+                                                     Class clazz) {
+
+        // check direct superclass
+        Class ret = clazz.getSuperclass();
+        boolean isOk = ret != null && ret != Object.class; // we don't want to shadow java.lang.Object
+        if ( isOk ) {
+            for ( int i = 0; isOk && ret != null && i < nodes.length; i++ ) {
+                isOk = nodes[i].getSinkPropagator().size() == 0 || nodes[i].isAssignableFrom( ret );
+            }
+        }
+
+        if ( !isOk ) {
+            // try the interfaces now...
+            Class[] interfaces = clazz.getInterfaces();
+            boolean notFound = true;
+            isOk = interfaces.length > 0;
+            for ( int i = 0; notFound && i < interfaces.length; i++ ) {
+                ret = interfaces[i];
+                isOk = interfaces[i] != Serializable.class && interfaces[i] != Cloneable.class && interfaces[i] != Comparable.class;
+                for ( int j = 0; isOk && j < nodes.length; j++ ) {
+                    isOk = nodes[j].getSinkPropagator().size() == 0 || nodes[j].isAssignableFrom( ret );
+                }
+                notFound = !isOk;
+            }
+            if ( notFound ) {
+                ret = null;
+            }
+        }
+
+        // ret now contains a superclass/interface that can be shadowed or null if none
+        return ret;
+    }
+
+    private void readObject(ObjectInputStream stream) throws IOException,
+                                                     ClassNotFoundException {
+        stream.defaultReadObject();
+        this.ruleBase = ((DroolsObjectInputStream) stream).getRuleBase();
+    }
+
+    /**
+     *
+     */
+    private void setInstantiator() {
+        this.instantiator = this.ruleBase.getObjenesis().getInstantiatorOf( this.shadowClass );
+    }
+
+    public Object getShadow(final Object fact) throws RuntimeDroolsException {
+        ShadowProxy proxy = null;
+        if ( isShadowEnabled() ) {
+            try {
+                if ( Collection.class.isAssignableFrom( this.shadowClass ) || Map.class.isAssignableFrom( this.shadowClass ) ) {
+                    // if it is a collection, try to instantiate using constructor
+                    try {
+                        proxy = (ShadowProxy) this.shadowClass.getConstructor( new Class[]{cls} ).newInstance( new Object[]{fact} );
+                    } catch ( Exception e ) {
+                        // not possible to instantiate using constructor
+                    }
+                }
+                if ( proxy == null ) {
+                    if ( this.instantiator == null ) {
+                        this.setInstantiator();
+                    }
+                    proxy = (ShadowProxy) this.instantiator.newInstance();
+                }
+                proxy.setShadowedObject( fact );
+            } catch ( final Exception e ) {
+                throw new RuntimeDroolsException( "Error creating shadow fact for object: " + fact,
+                                                  e );
+            }
+        }
+        return proxy;
+    }
+
+    public boolean isShadowEnabled() {
+        return this.shadowEnabled;
+    }
+
+    public void resetCache() {
+        this.objectTypeNodes = null;
+        defineShadowProxyData( cls );
+    }
+
+    public ObjectTypeNode[] getObjectTypeNodes() {
+        if ( this.objectTypeNodes == null ) {
+            this.objectTypeNodes = getMatchingObjectTypes( this.cls );
+        }
+        return this.objectTypeNodes;
+    }
+
+    private ObjectTypeNode[] getMatchingObjectTypes(final Class clazz) throws FactException {
+        final List<ObjectTypeNode> cache = new ArrayList<ObjectTypeNode>();
+
+        for( ObjectTypeNode node : ruleBase.getRete().getObjectTypeNodes( this.entryPoint ).values() ) {
+            if ( node.isAssignableFrom( clazz ) ) {
+                cache.add( node );
+            }
+        }
+
+        return (ObjectTypeNode[]) cache.toArray( new ObjectTypeNode[cache.size()] );
+    }
+
+    public boolean isActive() {
+        return getConcreteObjectTypeNode().getSinkPropagator().getSinks().length > 0;
+    }
+
+    public boolean isEvent() {
+        return this.concreteObjectTypeNode.getObjectType().isEvent();
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/CollectNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/CollectNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/CollectNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,386 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.reteoo;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.drools.common.BetaConstraints;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.Collect;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.PropagationContext;
+import org.drools.util.ArrayUtils;
+import org.drools.util.Entry;
+import org.drools.util.FactEntry;
+import org.drools.util.Iterator;
+import org.drools.util.ObjectHashMap.ObjectEntry;
+
+/**
+ * @author etirelli
+ *
+ */
+public class CollectNode extends BetaNode
+    implements
+    TupleSink,
+    ObjectSink {
+
+    private static final long                serialVersionUID = 400L;
+
+    private final Collect                    collect;
+    private final AlphaNodeFieldConstraint[] resultConstraints;
+    private final BetaConstraints            resultsBinder;
+    private final boolean                    unwrapRightObject;
+
+    /**
+     * Constructor.
+     * 
+     * @param id
+     *            The id for the node
+     * @param leftInput
+     *            The left input <code>TupleSource</code>.
+     * @param rightInput
+     *            The right input <code>ObjectSource</code>.
+     * @param resultConstraints
+     *            The alpha constraints to be applied to the resulting collection
+     * @param sourceBinder
+     *            The beta binder to be applied to the source facts
+     * @param resultsBinder
+     *            The beta binder to be applied to the resulting collection
+     * @param collect
+     *            The collect conditional element
+     */
+    public CollectNode(final int id,
+                       final TupleSource leftInput,
+                       final ObjectSource rightInput,
+                       final AlphaNodeFieldConstraint[] resultConstraints,
+                       final BetaConstraints sourceBinder,
+                       final BetaConstraints resultsBinder,
+                       final Collect collect,
+                       final boolean unwrapRight,
+                       final BuildContext context) {
+        super( id,
+               leftInput,
+               rightInput,
+               sourceBinder );
+        this.resultsBinder = resultsBinder;
+        this.resultConstraints = resultConstraints;
+        this.collect = collect;
+        this.unwrapRightObject = unwrapRight;
+        this.tupleMemoryEnabled = context.isTupleMemoryEnabled();
+    }
+
+    /**
+     * @inheritDoc
+     * 
+     *  When a new tuple is asserted into a CollectNode, do this:
+     *  
+     *  1. Select all matching objects from right memory
+     *  2. Add them to the resulting collection object
+     *  3. Apply resultConstraints and resultsBinder to the resulting collection
+     *  4. In case all of them evaluates to true do the following:
+     *  4.1. Create a new InternalFactHandle for the resulting collection and add it to the tuple
+     *  4.2. Propagate the tuple
+     *  
+     */
+    public void assertTuple(final ReteTuple leftTuple,
+                            final PropagationContext context,
+                            final InternalWorkingMemory workingMemory) {
+
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+
+        final Collection result = this.collect.instantiateResultObject();
+        final InternalFactHandle resultHandle = workingMemory.getFactHandleFactory().newFactHandle( result, false, workingMemory );
+        CollectResult colresult = new CollectResult();
+        colresult.handle = resultHandle;
+        colresult.propagated = false;
+        
+        // do not add tuple and result to the memory in sequential mode
+        if ( this.tupleMemoryEnabled ) {
+            memory.getTupleMemory().add( leftTuple );
+            memory.getCreatedHandles().put( leftTuple,
+                                            colresult,
+                                            false );
+        }
+
+
+        final Iterator it = memory.getFactHandleMemory().iterator( leftTuple );
+        this.constraints.updateFromTuple( workingMemory,
+                                          leftTuple );
+
+        for ( FactEntry entry = (FactEntry) it.next(); entry != null; entry = (FactEntry) it.next() ) {
+            InternalFactHandle handle = entry.getFactHandle();
+            if ( this.constraints.isAllowedCachedLeft( handle ) ) {
+                if( this.unwrapRightObject ) {
+                    handle = ((ReteTuple) handle.getObject()).getLastHandle(); 
+                }
+                result.add( handle.getObject() );
+            }
+        }
+        
+        this.constraints.resetTuple();
+
+        // First alpha node filters
+        boolean isAllowed = true;
+        for ( int i = 0, length = this.resultConstraints.length; i < length; i++ ) {
+            if ( !this.resultConstraints[i].isAllowed( resultHandle,
+                                                       workingMemory ) ) {
+                isAllowed = false;
+                break;
+            }
+        }
+        if ( isAllowed ) {
+            this.resultsBinder.updateFromTuple( workingMemory,
+                                                leftTuple );
+            if ( this.resultsBinder.isAllowedCachedLeft( resultHandle ) ) {
+                colresult.propagated = true;
+                this.sink.propagateAssertTuple( leftTuple,
+                                                resultHandle,
+                                                context,
+                                                workingMemory );
+            }
+        }
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public void retractTuple(final ReteTuple leftTuple,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+        memory.getTupleMemory().remove( leftTuple );
+        CollectResult result = (CollectResult) memory.getCreatedHandles().remove( leftTuple );
+        final InternalFactHandle handle = result.handle;
+
+        // if tuple was propagated
+        if ( result.propagated ) {
+
+            this.sink.propagateRetractTuple( leftTuple,
+                                             handle,
+                                             context,
+                                             workingMemory );
+
+            // Destroying the acumulate result object 
+            workingMemory.getFactHandleFactory().destroyFactHandle( handle );
+        }
+    }
+
+    /**
+     * @inheritDoc
+     * 
+     *  When a new object is asserted into a CollectNode, do this:
+     *  
+     *  1. Select all matching tuples from left memory
+     *  2. For each matching tuple, call a modify tuple
+     *  
+     */
+    public void assertObject(final InternalFactHandle handle,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+        memory.getFactHandleMemory().add( handle );
+        
+        if ( !this.tupleMemoryEnabled ) {
+            // do nothing here, as we know there are no left tuples at this stage in sequential mode.
+            return;
+        }        
+
+        this.constraints.updateFromFactHandle( workingMemory,
+                                               handle );
+
+        // need to clone the tuples to avoid concurrent modification exceptions
+        Entry[] tuples = memory.getTupleMemory().toArray();
+        for ( int i = 0; i < tuples.length; i++ ) {
+            ReteTuple tuple = (ReteTuple) tuples[i];
+            if ( this.constraints.isAllowedCachedRight( tuple ) ) {
+                this.modifyTuple( true,
+                                  tuple,
+                                  handle,
+                                  context,
+                                  workingMemory );
+            }
+        }
+
+        this.constraints.resetFactHandle();
+    }
+
+    /**
+     *  @inheritDoc
+     *  
+     *  If an object is retract, call modify tuple for each
+     *  tuple match.
+     */
+    public void retractObject(final InternalFactHandle handle,
+                              final PropagationContext context,
+                              final InternalWorkingMemory workingMemory) {
+
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+        if ( !memory.getFactHandleMemory().remove( handle ) ) {
+            return;
+        }
+
+        this.constraints.updateFromFactHandle( workingMemory,
+                                               handle );
+
+        // need to clone the tuples to avoid concurrent modification exceptions
+        Entry[] tuples = memory.getTupleMemory().toArray();
+        for ( int i = 0; i < tuples.length; i++ ) {
+            ReteTuple tuple = (ReteTuple) tuples[i];
+            if ( this.constraints.isAllowedCachedRight( tuple ) ) {
+                
+                this.modifyTuple( false,
+                                  tuple,
+                                  handle,
+                                  context,
+                                  workingMemory );
+            }
+        }
+        
+        this.constraints.resetFactHandle();
+    }
+
+    /**
+     * Modifies the results match for a tuple, retracting it and repropagating
+     * if constraints allow it
+     * 
+     * @param leftTuple
+     * @param handle
+     * @param context
+     * @param workingMemory
+     */
+    public void modifyTuple(final boolean isAssert,
+                            final ReteTuple leftTuple,
+                            InternalFactHandle handle,
+                            final PropagationContext context,
+                            final InternalWorkingMemory workingMemory) {
+
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+
+        CollectResult result = (CollectResult) memory.getCreatedHandles().get( leftTuple );
+
+        // if tuple was propagated
+        if ( result.propagated ) {
+            this.sink.propagateRetractTuple( leftTuple,
+                                             result.handle,
+                                             context,
+                                             workingMemory );
+            result.propagated = false;
+        }
+        
+        // if there is a subnetwork, we need to unwrapp the object from inside the tuple
+        if( this.unwrapRightObject ) {
+            handle = ((ReteTuple) handle.getObject()).getLastHandle(); 
+        }
+
+        if ( context.getType() == PropagationContext.ASSERTION ) {
+            ((Collection) result.handle.getObject()).add( handle.getObject() );
+        } else if ( context.getType() == PropagationContext.RETRACTION ) {
+            ((Collection) result.handle.getObject()).remove( handle.getObject() );
+        } else if ( context.getType() == PropagationContext.MODIFICATION || 
+                    context.getType() == PropagationContext.RULE_ADDITION || 
+                    context.getType() == PropagationContext.RULE_REMOVAL ) {
+            if( isAssert ) {
+                ((Collection) result.handle.getObject()).add( handle.getObject() );
+            } else {
+                ((Collection) result.handle.getObject()).remove( handle.getObject() );
+            }
+        }
+
+        // First alpha node filters
+        boolean isAllowed = true;
+        for ( int i = 0, length = this.resultConstraints.length; i < length; i++ ) {
+            if ( !this.resultConstraints[i].isAllowed( result.handle,
+                                                       workingMemory ) ) {
+                isAllowed = false;
+                break;
+            }
+        }
+        if ( isAllowed ) {
+            this.resultsBinder.updateFromTuple( workingMemory,
+                                                leftTuple );
+            if ( this.resultsBinder.isAllowedCachedLeft( result.handle ) ) {
+                result.propagated = true;
+                this.sink.propagateAssertTuple( leftTuple,
+                                                result.handle,
+                                                context,
+                                                workingMemory );
+            }
+            
+            this.resultsBinder.resetTuple();
+        }
+    }
+
+    public void updateSink(final TupleSink sink,
+                           final PropagationContext context,
+                           final InternalWorkingMemory workingMemory) {
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+
+        final Iterator it = memory.getCreatedHandles().iterator();
+
+        for ( ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next() ) {
+            CollectResult result = (CollectResult) entry.getValue();
+            sink.assertTuple( new ReteTuple( (ReteTuple) entry.getKey(),
+                                             result.handle ),
+                              context,
+                              workingMemory );
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.BaseNode#hashCode()
+     */
+    public int hashCode() {
+        return this.leftInput.hashCode() ^ this.rightInput.hashCode() ^ this.collect.hashCode() ^ this.resultsBinder.hashCode() ^ ArrayUtils.hashCode( this.resultConstraints );
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof CollectNode) ) {
+            return false;
+        }
+
+        final CollectNode other = (CollectNode) object;
+
+        if ( this.getClass() != other.getClass() || (!this.leftInput.equals( other.leftInput )) || (!this.rightInput.equals( other.rightInput )) || (!this.constraints.equals( other.constraints )) ) {
+            return false;
+        }
+
+        return this.collect.equals( other.collect ) && resultsBinder.equals( other.resultsBinder ) && Arrays.equals( this.resultConstraints,
+                                                                                                                     other.resultConstraints );
+    }
+
+    public String toString() {
+        return "[ " + this.getClass().getName() + "(" + this.id + ") ]";
+    }
+
+    private static class CollectResult {
+        // keeping attributes public just for performance
+        public InternalFactHandle handle;
+        public boolean            propagated;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/CompositeObjectSinkAdapter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/CompositeObjectSinkAdapter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/CompositeObjectSinkAdapter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,743 @@
+package org.drools.reteoo;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.Operator;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.LiteralConstraint;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.FieldValue;
+import org.drools.spi.PropagationContext;
+import org.drools.util.Iterator;
+import org.drools.util.LinkedList;
+import org.drools.util.LinkedListNode;
+import org.drools.util.ObjectHashMap;
+import org.drools.util.ObjectHashMap.ObjectEntry;
+
+public class CompositeObjectSinkAdapter
+    implements
+    ObjectSinkPropagator {
+
+    //    /** You can override this property via a system property (eg -Ddrools.hashThreshold=4) */
+    //    public static final String HASH_THRESHOLD_SYSTEM_PROPERTY = "drools.hashThreshold";
+    //
+    //    /** The threshold for when hashing kicks in */
+    //    public static final int    THRESHOLD_TO_HASH              = Integer.parseInt( System.getProperty( HASH_THRESHOLD_SYSTEM_PROPERTY,
+    //                                                                                                      "3" ) );
+
+    private static final long serialVersionUID = 400L;
+    ObjectSinkNodeList        otherSinks;
+    ObjectSinkNodeList        hashableSinks;
+
+    LinkedList                hashedFieldIndexes;
+
+    ObjectHashMap             hashedSinkMap;
+
+    private final int         alphaNodeHashingThreshold;
+
+    public CompositeObjectSinkAdapter() {
+        this( 3 );
+    }
+
+    public CompositeObjectSinkAdapter(final int alphaNodeHashingThreshold) {
+        this.alphaNodeHashingThreshold = alphaNodeHashingThreshold;
+    }
+
+    public void addObjectSink(final ObjectSink sink) {
+        if ( sink instanceof AlphaNode ) {
+            final AlphaNode alphaNode = (AlphaNode) sink;
+            final AlphaNodeFieldConstraint fieldConstraint = alphaNode.getConstraint();
+
+            if ( fieldConstraint instanceof LiteralConstraint ) {
+                final LiteralConstraint literalConstraint = (LiteralConstraint) fieldConstraint;
+                final Evaluator evaluator = literalConstraint.getEvaluator();
+
+                if ( evaluator.getOperator() == Operator.EQUAL && literalConstraint.getFieldExtractor().getValueType() != ValueType.OBJECT_TYPE ) {
+                    final int index = literalConstraint.getFieldExtractor().getIndex();
+                    final FieldIndex fieldIndex = registerFieldIndex( index,
+                                                                      literalConstraint.getFieldExtractor() );
+
+                    if ( fieldIndex.getCount() >= this.alphaNodeHashingThreshold && this.alphaNodeHashingThreshold != 0 ) {
+                        if ( !fieldIndex.isHashed() ) {
+                            hashSinks( fieldIndex );
+                        }
+                        final FieldValue value = literalConstraint.getField();
+                        // no need to check, we know  the sink  does not exist
+                        this.hashedSinkMap.put( new HashKey( index,
+                                                             value,
+                                                             fieldIndex.getFieldExtractor() ),
+                                                sink,
+                                                false );
+                    } else {
+                        if ( this.hashableSinks == null ) {
+                            this.hashableSinks = new ObjectSinkNodeList();
+                        }
+                        this.hashableSinks.add( (ObjectSinkNode) sink );
+                    }
+                    return;
+                }
+
+            }
+        }
+
+        if ( this.otherSinks == null ) {
+            this.otherSinks = new ObjectSinkNodeList();
+        }
+
+        this.otherSinks.add( (ObjectSinkNode) sink );
+    }
+
+    public void removeObjectSink(final ObjectSink sink) {
+        if ( sink instanceof AlphaNode ) {
+            final AlphaNode alphaNode = (AlphaNode) sink;
+            final AlphaNodeFieldConstraint fieldConstraint = alphaNode.getConstraint();
+
+            if ( fieldConstraint instanceof LiteralConstraint ) {
+                final LiteralConstraint literalConstraint = (LiteralConstraint) fieldConstraint;
+                final Evaluator evaluator = literalConstraint.getEvaluator();
+                final FieldValue value = literalConstraint.getField();
+
+                if ( evaluator.getOperator() == Operator.EQUAL && literalConstraint.getFieldExtractor().getValueType() != ValueType.OBJECT_TYPE ) {
+                    final int index = literalConstraint.getFieldExtractor().getIndex();
+                    final FieldIndex fieldIndex = unregisterFieldIndex( index );
+
+                    if ( fieldIndex.isHashed() ) {
+                        HashKey hashKey = new HashKey( index,
+                                                       value,
+                                                       fieldIndex.getFieldExtractor() );
+                        this.hashedSinkMap.remove( hashKey );
+                        if ( fieldIndex.getCount() <= this.alphaNodeHashingThreshold - 1 ) {
+                            // we have less than three so unhash
+                            unHashSinks( fieldIndex );
+                        }
+                    } else {
+                        this.hashableSinks.remove( (ObjectSinkNode) sink );
+                    }
+
+                    if ( this.hashableSinks != null && this.hashableSinks.isEmpty() ) {
+                        this.hashableSinks = null;
+                    }
+
+                    return;
+                }
+            }
+        }
+
+        this.otherSinks.remove( (ObjectSinkNode) sink );
+
+        if ( this.otherSinks.isEmpty() ) {
+            this.otherSinks = null;
+        }
+    }
+
+    public void hashSinks(final FieldIndex fieldIndex) {
+        final int index = fieldIndex.getIndex();
+
+        final List list = new ArrayList();
+
+        if ( this.hashedSinkMap == null ) {
+            this.hashedSinkMap = new ObjectHashMap();
+        }
+
+        for ( ObjectSinkNode sink = this.hashableSinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode() ) {
+            final AlphaNode alphaNode = (AlphaNode) sink;
+            final AlphaNodeFieldConstraint fieldConstraint = alphaNode.getConstraint();
+            final LiteralConstraint literalConstraint = (LiteralConstraint) fieldConstraint;
+            final Evaluator evaluator = literalConstraint.getEvaluator();
+            if ( evaluator.getOperator() == Operator.EQUAL && index == literalConstraint.getFieldExtractor().getIndex() ) {
+                final FieldValue value = literalConstraint.getField();
+                list.add( sink );
+                this.hashedSinkMap.put( new HashKey( index,
+                                                     value,
+                                                     fieldIndex.getFieldExtractor() ),
+                                        sink );
+            }
+        }
+
+        for ( final java.util.Iterator it = list.iterator(); it.hasNext(); ) {
+            final ObjectSinkNode sink = (ObjectSinkNode) it.next();
+            this.hashableSinks.remove( sink );
+        }
+
+        if ( this.hashableSinks.isEmpty() ) {
+            this.hashableSinks = null;
+        }
+
+        fieldIndex.setHashed( true );
+    }
+
+    public void unHashSinks(final FieldIndex fieldIndex) {
+        final int index = fieldIndex.getIndex();
+
+        final List sinks = new ArrayList();
+
+        //iterate twice as custom iterator is immutable
+        final Iterator mapIt = this.hashedSinkMap.newIterator();
+        for ( ObjectHashMap.ObjectEntry e = (ObjectHashMap.ObjectEntry) mapIt.next(); e != null; ) {
+
+            sinks.add( e.getValue() );
+            e = (ObjectHashMap.ObjectEntry) mapIt.next();
+        }
+
+        for ( final java.util.Iterator iter = sinks.iterator(); iter.hasNext(); ) {
+            final AlphaNode sink = (AlphaNode) iter.next();
+            final AlphaNode alphaNode = sink;
+            final AlphaNodeFieldConstraint fieldConstraint = alphaNode.getConstraint();
+            final LiteralConstraint literalConstraint = (LiteralConstraint) fieldConstraint;
+            final Evaluator evaluator = literalConstraint.getEvaluator();
+            if ( evaluator.getOperator() == Operator.EQUAL && index == literalConstraint.getFieldExtractor().getIndex() ) {
+                final FieldValue value = literalConstraint.getField();
+                if ( this.hashableSinks == null ) {
+                    this.hashableSinks = new ObjectSinkNodeList();
+                }
+                this.hashableSinks.add( sink );
+                this.hashedSinkMap.remove( new HashKey( index,
+                                                        value,
+                                                        fieldIndex.getFieldExtractor() ) );
+            };
+        }
+
+        if ( this.hashedSinkMap.isEmpty() ) {
+            this.hashedSinkMap = null;
+        }
+
+        fieldIndex.setHashed( false );
+    }
+
+    /**
+     * Returns a FieldIndex which Keeps a count on how many times a particular field is used with an equality check in the sinks.
+     * @param index
+     * @param fieldExtractor
+     * @return
+     */
+    private FieldIndex registerFieldIndex(final int index,
+                                          final FieldExtractor fieldExtractor) {
+        FieldIndex fieldIndex = null;
+
+        // is linkedlist null, if so create and add
+        if ( this.hashedFieldIndexes == null ) {
+            this.hashedFieldIndexes = new LinkedList();
+            fieldIndex = new FieldIndex( index,
+                                         fieldExtractor );
+            this.hashedFieldIndexes.add( fieldIndex );
+        }
+
+        // still null, so see if it already exists
+        if ( fieldIndex == null ) {
+            fieldIndex = findFieldIndex( index );
+        }
+
+        // doesn't exist so create it
+        if ( fieldIndex == null ) {
+            fieldIndex = new FieldIndex( index,
+                                         fieldExtractor );
+            this.hashedFieldIndexes.add( fieldIndex );
+        }
+
+        fieldIndex.increaseCounter();
+
+        return fieldIndex;
+    }
+
+    private FieldIndex unregisterFieldIndex(final int index) {
+        final FieldIndex fieldIndex = findFieldIndex( index );
+        fieldIndex.decreaseCounter();
+
+        // if the fieldcount is 0 then remove it from the linkedlist
+        if ( fieldIndex.getCount() == 0 ) {
+            this.hashedFieldIndexes.remove( fieldIndex );
+
+            // if the linkedlist is empty then null it
+            if ( this.hashedFieldIndexes.isEmpty() ) {
+                this.hashedFieldIndexes = null;
+            }
+        }
+
+        return fieldIndex;
+    }
+
+    private FieldIndex findFieldIndex(final int index) {
+        for ( FieldIndex node = (FieldIndex) this.hashedFieldIndexes.getFirst(); node != null; node = (FieldIndex) node.getNext() ) {
+            if ( node.getIndex() == index ) {
+                return node;
+            }
+        }
+
+        return null;
+    }
+
+    public void propagateAssertObject(final InternalFactHandle handle,
+                                      final PropagationContext context,
+                                      final InternalWorkingMemory workingMemory) {
+        final Object object = handle.getObject();
+
+        // Iterates t he FieldIndex collection, which tells you if particularly field is hashed or not
+        // if the field is hashed then it builds the hashkey to return the correct sink for the current objects slot's
+        // value, one object may have multiple fields indexed.
+        if ( this.hashedFieldIndexes != null ) {
+            // Iterate the FieldIndexes to see if any are hashed        
+            for ( FieldIndex fieldIndex = (FieldIndex) this.hashedFieldIndexes.getFirst(); fieldIndex != null; fieldIndex = (FieldIndex) fieldIndex.getNext() ) {
+                if ( !fieldIndex.isHashed() ) {
+                    continue;
+                }
+                // this field is hashed so set the existing hashKey and see if there is a sink for it
+                final int index = fieldIndex.getIndex();
+                final FieldExtractor extractor = fieldIndex.getFieldExtactor();
+                HashKey hashKey = new HashKey( index,
+                                               object,
+                                               fieldIndex.getFieldExtractor() );
+                final ObjectSink sink = (ObjectSink) this.hashedSinkMap.get( hashKey );
+                if ( sink != null ) {
+                    // The sink exists so propagate
+                    sink.assertObject( handle,
+                                       context,
+                                       workingMemory );
+                }
+            }
+        }
+
+        // propagate unhashed
+        if ( this.hashableSinks != null ) {
+            for ( ObjectSinkNode sink = this.hashableSinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode() ) {
+                sink.assertObject( handle,
+                                   context,
+                                   workingMemory );
+            }
+        }
+
+        if ( this.otherSinks != null ) {
+            // propagate others
+            for ( ObjectSinkNode sink = this.otherSinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode() ) {
+                sink.assertObject( handle,
+                                   context,
+                                   workingMemory );
+            }
+        }
+
+    }
+
+    public void propagateRetractObject(final InternalFactHandle handle,
+                                       final PropagationContext context,
+                                       final InternalWorkingMemory workingMemory,
+                                       final boolean useHash) {
+        if ( this.hashedFieldIndexes != null ) {
+            if ( useHash && this.hashedSinkMap != null ) {
+                final Object object = handle.getObject();
+                // Iterate the FieldIndexes to see if any are hashed        
+                for ( FieldIndex fieldIndex = (FieldIndex) this.hashedFieldIndexes.getFirst(); fieldIndex != null; fieldIndex = (FieldIndex) fieldIndex.getNext() ) {
+                    // this field is hashed so set the existing hashKey and see if there is a sink for it
+                    if ( !fieldIndex.isHashed() ) {
+                        continue;
+                    }
+
+                    final int index = fieldIndex.getIndex();
+                    HashKey hashKey = new HashKey( index,
+                                                   object,
+                                                   fieldIndex.getFieldExtactor() );
+                    final ObjectSink sink = (ObjectSink) this.hashedSinkMap.get( hashKey );
+                    if ( sink != null ) {
+                        // The sink exists so propagate
+                        sink.retractObject( handle,
+                                            context,
+                                            workingMemory );
+                    }
+                }
+            } else if ( this.hashedSinkMap != null ) {
+                final Iterator it = this.hashedSinkMap.newIterator();
+                for ( ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next() ) {
+                    final ObjectSink sink = (ObjectSink) entry.getValue();
+                    sink.retractObject( handle,
+                                        context,
+                                        workingMemory );
+                }
+            }
+        }
+
+        if ( this.hashableSinks != null ) {
+            // we can't retrieve hashed sinks, as the field value might have changed, so we have to iterate and propagate to all hashed sinks
+            for ( ObjectSinkNode sink = this.hashableSinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode() ) {
+                sink.retractObject( handle,
+                                    context,
+                                    workingMemory );
+            }
+        }
+
+        if ( this.otherSinks != null ) {
+            // propagate others
+            for ( ObjectSinkNode sink = this.otherSinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode() ) {
+                sink.retractObject( handle,
+                                    context,
+                                    workingMemory );
+            }
+        }
+    }
+
+    public ObjectSink[] getSinks() {
+        final List list = new ArrayList();
+
+        if ( this.otherSinks != null ) {
+            for ( ObjectSinkNode sink = this.otherSinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode() ) {
+                list.add( sink );
+            }
+        }
+
+        if ( this.hashableSinks != null ) {
+            for ( ObjectSinkNode sink = this.hashableSinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode() ) {
+                list.add( sink );
+            }
+        }
+
+        if ( this.hashedSinkMap != null ) {
+            final Iterator it = this.hashedSinkMap.newIterator();
+            for ( ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next() ) {
+                final ObjectSink sink = (ObjectSink) entry.getValue();
+                list.add( sink );
+            }
+        }
+
+        return (ObjectSink[]) list.toArray( new ObjectSink[list.size()] );
+    }
+
+    public int size() {
+        int size = 0;
+        size += ((this.otherSinks != null) ? this.otherSinks.size() : 0);
+        size += ((this.hashableSinks != null) ? this.hashableSinks.size() : 0);
+        size += ((this.hashedSinkMap != null) ? this.hashedSinkMap.size() : 0);
+        return size;
+    }
+
+    public static class HashKey
+        implements
+        Serializable {
+        private static final long serialVersionUID = 400L;
+
+        private static final byte OBJECT           = 1;
+        private static final byte LONG             = 2;
+        private static final byte DOUBLE           = 3;
+        private static final byte BOOL             = 4;
+
+        private int               index;
+
+        private byte              type;
+        private Object            ovalue;
+        private long              lvalue;
+        private boolean           bvalue;
+        private double            dvalue;
+
+        private boolean           isNull;
+
+        private int               hashCode;
+
+        public HashKey() {
+        }
+
+        public HashKey(final int index,
+                       final FieldValue value,
+                       final Extractor extractor) {
+            this.setValue( index,
+                           extractor,
+                           value );
+        }
+
+        public HashKey(final int index,
+                       final Object value,
+                       final Extractor extractor) {
+            this.setValue( index,
+                           value,
+                           extractor );
+        }
+
+        public int getIndex() {
+            return this.index;
+        }
+
+        public void setValue(final int index,
+                             final Object value,
+                             final Extractor extractor) {
+            this.index = index;
+            final ValueType vtype = extractor.getValueType();
+
+            isNull = extractor.isNullValue( null,
+                                            value );
+
+            if ( vtype.isBoolean() ) {
+                this.type = BOOL;
+                if ( !isNull ) {
+                    this.bvalue = extractor.getBooleanValue( null,
+                                                             value );
+                    this.setHashCode( this.bvalue ? 1231 : 1237 );
+                } else {
+                    this.setHashCode( 0 );
+                }
+            } else if ( vtype.isIntegerNumber() || vtype.isChar() ) {
+                this.type = LONG;
+                if ( !isNull ) {
+                    this.lvalue = extractor.getLongValue( null,
+                                                          value );
+                    this.setHashCode( (int) (this.lvalue ^ (this.lvalue >>> 32)) );
+                } else {
+                    this.setHashCode( 0 );
+                }
+            } else if ( vtype.isFloatNumber() ) {
+                this.type = DOUBLE;
+                if ( !isNull ) {
+                    this.dvalue = extractor.getDoubleValue( null,
+                                                            value );
+                    final long temp = Double.doubleToLongBits( this.dvalue );
+                    this.setHashCode( (int) (temp ^ (temp >>> 32)) );
+                } else {
+                    this.setHashCode( 0 );
+                }
+            } else {
+                this.type = OBJECT;
+                if ( !isNull ) {
+                    this.ovalue = extractor.getValue( null,
+                                                      value );
+                    this.setHashCode( this.ovalue != null ? this.ovalue.hashCode() : 0 );
+                } else {
+                    this.setHashCode( 0 );
+                }
+            }
+        }
+
+        public void setValue(final int index,
+                             final Extractor extractor,
+                             final FieldValue value) {
+            this.index = index;
+
+            this.isNull = value.isNull();
+            final ValueType vtype = extractor.getValueType();
+
+            if ( vtype.isBoolean() ) {
+                this.type = BOOL;
+                if ( !isNull ) {
+                    this.bvalue = value.getBooleanValue();
+                    this.setHashCode( this.bvalue ? 1231 : 1237 );
+                } else {
+                    this.setHashCode( 0 );
+                }
+            } else if ( vtype.isIntegerNumber() ) {
+                this.type = LONG;
+                if ( !isNull ) {
+                    this.lvalue = value.getLongValue();
+                    this.setHashCode( (int) (this.lvalue ^ (this.lvalue >>> 32)) );
+                } else {
+                    this.setHashCode( 0 );
+                }
+            } else if ( vtype.isFloatNumber() ) {
+                this.type = DOUBLE;
+                if ( !isNull ) {
+                    this.dvalue = value.getDoubleValue();
+                    final long temp = Double.doubleToLongBits( this.dvalue );
+                    this.setHashCode( (int) (temp ^ (temp >>> 32)) );
+                } else {
+                    this.setHashCode( 0 );
+                }
+            } else {
+                this.type = OBJECT;
+                if ( !isNull ) {
+                    this.ovalue = value.getValue();
+                    this.setHashCode( this.ovalue != null ? this.ovalue.hashCode() : 0 );
+                } else {
+                    this.setHashCode( 0 );
+                }
+            }
+        }
+
+        private void setHashCode(final int hashSeed) {
+            final int PRIME = 31;
+            int result = 1;
+            result = PRIME * result + hashSeed;
+            result = PRIME * result + this.index;
+            this.hashCode = result;
+        }
+
+        public boolean getBooleanValue() {
+            switch ( this.type ) {
+                case BOOL :
+                    return this.bvalue;
+                case OBJECT :
+                    if ( this.ovalue == null ) {
+                        return false;
+                    } else if ( this.ovalue instanceof Boolean ) {
+                        return ((Boolean) this.ovalue).booleanValue();
+                    } else if ( this.ovalue instanceof String ) {
+                        return Boolean.valueOf( (String) this.ovalue ).booleanValue();
+                    } else {
+                        throw new ClassCastException( "Can't convert " + this.ovalue.getClass() + " to a boolean value." );
+                    }
+                case LONG :
+                    throw new ClassCastException( "Can't convert long to a boolean value." );
+                case DOUBLE :
+                    throw new ClassCastException( "Can't convert double to a boolean value." );
+
+            }
+            return false;
+        }
+
+        public long getLongValue() {
+            switch ( this.type ) {
+                case BOOL :
+                    return this.bvalue ? 1 : 0;
+                case OBJECT :
+                    if ( this.ovalue == null ) {
+                        return 0;
+                    } else if ( this.ovalue instanceof Number ) {
+                        return ((Number) this.ovalue).longValue();
+                    } else if ( this.ovalue instanceof String ) {
+                        return Long.parseLong( (String) this.ovalue );
+                    } else {
+                        throw new ClassCastException( "Can't convert " + this.ovalue.getClass() + " to a long value." );
+                    }
+                case LONG :
+                    return this.lvalue;
+                case DOUBLE :
+                    return (long) this.dvalue;
+
+            }
+            return 0;
+        }
+
+        public double getDoubleValue() {
+            switch ( this.type ) {
+                case BOOL :
+                    return this.bvalue ? 1 : 0;
+                case OBJECT :
+                    if ( this.ovalue == null ) {
+                        return 0;
+                    } else if ( this.ovalue instanceof Number ) {
+                        return ((Number) this.ovalue).doubleValue();
+                    } else if ( this.ovalue instanceof String ) {
+                        return Double.parseDouble( (String) this.ovalue );
+                    } else {
+                        throw new ClassCastException( "Can't convert " + this.ovalue.getClass() + " to a double value." );
+                    }
+                case LONG :
+                    return this.lvalue;
+                case DOUBLE :
+                    return this.dvalue;
+            }
+            return 0;
+        }
+
+        public Object getObjectValue() {
+            switch ( this.type ) {
+                case BOOL :
+                    return this.bvalue ? Boolean.TRUE : Boolean.FALSE;
+                case OBJECT :
+                    return this.ovalue;
+                case LONG :
+                    return new Long( this.lvalue );
+                case DOUBLE :
+                    return new Double( this.dvalue );
+            }
+            return null;
+        }
+
+        public int hashCode() {
+            return this.hashCode;
+        }
+
+        public boolean equals(final Object object) {
+            final HashKey other = (HashKey) object;
+
+            if ( this.isNull ) {
+                return (other.isNull );
+            }
+
+            switch ( this.type ) {
+                case BOOL :
+                    return (this.index == other.index) && (this.bvalue == other.getBooleanValue());
+                case LONG :
+                    return (this.index == other.index) && (this.lvalue == other.getLongValue());
+                case DOUBLE :
+                    return (this.index == other.index) && (this.dvalue == other.getDoubleValue());
+                case OBJECT :
+                    final Object otherValue = other.getObjectValue();
+                    if ( (this.ovalue != null) && (this.ovalue instanceof Number) && (otherValue instanceof Number) ) {
+                        return (this.index == other.index) && (((Number) this.ovalue).doubleValue() == ((Number) otherValue).doubleValue());
+                    }
+                    return (this.index == other.index) && (this.ovalue == null ? otherValue == null : this.ovalue.equals( otherValue ));
+            }
+            return false;
+        }
+
+    }
+
+    public static class FieldIndex
+        implements
+        LinkedListNode {
+        private static final long serialVersionUID = 400L;
+        private final int         index;
+        private FieldExtractor    fieldExtactor;
+
+        private int               count;
+
+        private boolean           hashed;
+
+        private LinkedListNode    previous;
+        private LinkedListNode    next;
+
+        public FieldIndex(final int index,
+                          final FieldExtractor fieldExtractor) {
+            this.index = index;
+            this.fieldExtactor = fieldExtractor;
+        }
+
+        public FieldExtractor getFieldExtractor() {
+            return this.fieldExtactor;
+        }
+
+        public int getIndex() {
+            return this.index;
+        }
+
+        public int getCount() {
+            return this.count;
+        }
+
+        public FieldExtractor getFieldExtactor() {
+            return this.fieldExtactor;
+        }
+
+        public boolean isHashed() {
+            return this.hashed;
+        }
+
+        public void setHashed(final boolean hashed) {
+            this.hashed = hashed;
+        }
+
+        public void increaseCounter() {
+            this.count++;
+        }
+
+        public void decreaseCounter() {
+            this.count--;
+        }
+
+        public LinkedListNode getNext() {
+            return this.next;
+        }
+
+        public LinkedListNode getPrevious() {
+            return this.previous;
+        }
+
+        public void setNext(final LinkedListNode next) {
+            this.next = next;
+
+        }
+
+        public void setPrevious(final LinkedListNode previous) {
+            this.previous = previous;
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/CompositeTupleSinkAdapter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/CompositeTupleSinkAdapter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/CompositeTupleSinkAdapter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,168 @@
+package org.drools.reteoo;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+
+public class CompositeTupleSinkAdapter
+    implements
+    TupleSinkPropagator {
+    private TupleSinkNodeList sinks;
+
+    public CompositeTupleSinkAdapter() {
+        this.sinks = new TupleSinkNodeList();
+    }
+
+    public void addTupleSink(final TupleSink sink) {
+        this.sinks.add( (TupleSinkNode) sink );
+    }
+
+    public void removeTupleSink(final TupleSink sink) {
+        this.sinks.remove( (TupleSinkNode) sink );
+    }
+
+    public void propagateAssertTuple(final ReteTuple tuple,
+                                     final InternalFactHandle handle,
+                                     final PropagationContext context,
+                                     final InternalWorkingMemory workingMemory) {
+
+        for ( TupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextTupleSinkNode() ) {
+            sink.assertTuple( new ReteTuple( tuple,
+                                             handle ),
+                              context,
+                              workingMemory );
+        }
+    }
+
+    public void propagateAssertTuple(final ReteTuple tuple,
+                                     final PropagationContext context,
+                                     final InternalWorkingMemory workingMemory) {
+        for ( TupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextTupleSinkNode() ) {
+            sink.assertTuple( new ReteTuple( tuple ),
+                              context,
+                              workingMemory );
+        }
+    }
+
+    public void propagateRetractTuple(final ReteTuple tuple,
+                                      final InternalFactHandle handle,
+                                      final PropagationContext context,
+                                      final InternalWorkingMemory workingMemory) {
+        for ( TupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextTupleSinkNode() ) {
+            sink.retractTuple( new ReteTuple( tuple,
+                                              handle ),
+                               context,
+                               workingMemory );
+        }
+    }
+
+    public void propagateRetractTuple(final ReteTuple tuple,
+                                      final PropagationContext context,
+                                      final InternalWorkingMemory workingMemory) {
+        for ( TupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextTupleSinkNode() ) {
+            sink.retractTuple( new ReteTuple( tuple ),
+                               context,
+                               workingMemory );
+        }
+    }
+
+    public void createAndPropagateAssertTuple(final InternalFactHandle handle,
+                                              final PropagationContext context,
+                                              final InternalWorkingMemory workingMemory) {
+        for ( TupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextTupleSinkNode() ) {
+            sink.assertTuple( new ReteTuple( handle ),
+                              context,
+                              workingMemory );
+        }
+    }
+
+    public void createAndPropagateRetractTuple(final InternalFactHandle handle,
+                                               final PropagationContext context,
+                                               final InternalWorkingMemory workingMemory) {
+        for ( TupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextTupleSinkNode() ) {
+            sink.retractTuple( new ReteTuple( handle ),
+                               context,
+                               workingMemory );
+        }
+    }
+
+    public TupleSink[] getSinks() {
+        final TupleSink[] sinkArray = new TupleSink[this.sinks.size()];
+
+        int i = 0;
+        for ( TupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextTupleSinkNode() ) {
+            sinkArray[i++] = sink;
+        }
+
+        return sinkArray;
+    }
+
+    //    public void propagateNewTupleSink(TupleMatch tupleMatch,
+    //                                      PropagationContext context,
+    //                                      InternalWorkingMemory workingMemory) {
+    //
+    //        final TupleSink sink = sinks.getLast();
+    //        final ReteTuple tuple = new ReteTuple( tupleMatch.getTuple(),
+    //                                               tupleMatch.getObjectMatches().getFactHandle(),
+    //                                               sink );
+    //        tupleMatch.addJoinedTuple( tuple );
+    //        tuple.assertTuple( context,
+    //                           workingMemory );
+    //    }
+    //
+    //    public void propagateNewTupleSink(ReteTuple tuple,
+    //                                      PropagationContext context,
+    //                                      InternalWorkingMemory workingMemory) {
+    //
+    //        final TupleSink sink = sinks.getLast();
+    //        ReteTuple child = new ReteTuple( tuple,
+    //                                         sink );
+    //        tuple.addChildEntry( child );
+    //        child.assertTuple( context,
+    //                           workingMemory );
+    //    }
+    //
+    //    public void propagateNewTupleSink(InternalFactHandle handle,
+    //                                      LinkedList list,
+    //                                      PropagationContext context,
+    //                                      InternalWorkingMemory workingMemory) {
+    //        TupleSink sink = this.sinks.getLast();
+    //        ReteTuple tuple = new ReteTuple( handle,
+    //                                         sink );
+    //        list.add( new LinkedListEntry( tuple ) );
+    //        tuple.assertTuple( context,
+    //                           workingMemory );
+    //    }
+    //
+    //    /**
+    //     * @inheritDoc
+    //     */
+    //    public List getPropagatedTuples(final Map memory,
+    //                                    final InternalWorkingMemory workingMemory,
+    //                                    final TupleSink sink) {
+    //        int index = 0;
+    //        for ( TupleSinkNode node = this.sinks.getFirst(); node != null; node = node.getNextTupleSinkNode() ) {
+    //            if ( node.equals( sink ) ) {
+    //                break;
+    //            }
+    //            index++;
+    //        }
+    //
+    //        final List propagatedTuples = new ArrayList( memory.size() );
+    //
+    //        for ( final Iterator it = memory.values().iterator(); it.hasNext(); ) {
+    //            final LinkedList tuples = (LinkedList) it.next();
+    //            LinkedListEntry wrapper = (LinkedListEntry) tuples.getFirst();
+    //            for ( int i = 0; i < index; i++ ) {
+    //                wrapper = (LinkedListEntry) wrapper.getNext();
+    //            }
+    //            propagatedTuples.add( wrapper.getObject() );
+    //        }
+    //
+    //        return propagatedTuples;
+    //    }
+
+    public int size() {
+        return this.sinks.size();
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/EmptyObjectSinkAdapter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/EmptyObjectSinkAdapter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/EmptyObjectSinkAdapter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,44 @@
+package org.drools.reteoo;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+
+public class EmptyObjectSinkAdapter
+    implements
+    ObjectSinkPropagator {
+
+    private static final long serialVersionUID = -631743913176779720L;
+
+    private static final EmptyObjectSinkAdapter instance = new EmptyObjectSinkAdapter();
+    
+    private static final ObjectSink[] SINK_LIST = new ObjectSink[0];
+
+    public static EmptyObjectSinkAdapter getInstance() {
+        return instance;
+    }
+
+    private EmptyObjectSinkAdapter() {
+    }
+
+    public void propagateAssertObject(final InternalFactHandle handle,
+                                      final PropagationContext context,
+                                      final InternalWorkingMemory workingMemory) {
+
+    }
+
+    public void propagateRetractObject(final InternalFactHandle handle,
+                                       final PropagationContext context,
+                                       final InternalWorkingMemory workingMemory,
+                                       final boolean useHash) {
+    }
+
+    public ObjectSink[] getSinks() {
+        return SINK_LIST;
+    }
+    
+    public int size() {
+        return 0;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/EmptyTupleSinkAdapter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/EmptyTupleSinkAdapter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/EmptyTupleSinkAdapter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,59 @@
+package org.drools.reteoo;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+
+public class EmptyTupleSinkAdapter
+    implements
+    TupleSinkPropagator {
+
+    private static final EmptyTupleSinkAdapter instance = new EmptyTupleSinkAdapter();
+
+    public static final EmptyTupleSinkAdapter getInstance() {
+        return instance;
+    }
+
+    private EmptyTupleSinkAdapter() {
+    }
+
+    public void propagateAssertTuple(final ReteTuple tuple,
+                                     final InternalFactHandle handle,
+                                     final PropagationContext context,
+                                     final InternalWorkingMemory workingMemory) {
+    }
+
+    public void propagateAssertTuple(final ReteTuple tuple,
+                                     final PropagationContext context,
+                                     final InternalWorkingMemory workingMemory) {
+    }
+
+    public void propagateRetractTuple(final ReteTuple tuple,
+                                      final InternalFactHandle handle,
+                                      final PropagationContext context,
+                                      final InternalWorkingMemory workingMemory) {
+    }
+
+    public void propagateRetractTuple(final ReteTuple tuple,
+                                      final PropagationContext context,
+                                      final InternalWorkingMemory workingMemory) {
+    }
+
+    public void createAndPropagateAssertTuple(final InternalFactHandle handle,
+                                              final PropagationContext context,
+                                              final InternalWorkingMemory workingMemory) {
+    }
+
+    public void createAndPropagateRetractTuple(final InternalFactHandle handle,
+                                               final PropagationContext context,
+                                               final InternalWorkingMemory workingMemory) {
+    }
+
+    public TupleSink[] getSinks() {
+        return new TupleSink[]{};
+    }
+
+    public int size() {
+        return 0;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/EntryPointNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/EntryPointNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/EntryPointNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,279 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2007 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.
+ * 
+ * Created on January 8th, 2007
+ */
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.base.ShadowProxy;
+import org.drools.common.BaseNode;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.NodeMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.EntryPoint;
+import org.drools.spi.ObjectType;
+import org.drools.spi.PropagationContext;
+import org.drools.util.FactEntry;
+import org.drools.util.FactHashTable;
+import org.drools.util.Iterator;
+
+/**
+ * A node that is an entry point into the Rete network.
+ *
+ * As we move the design to support network partitions and concurrent processing 
+ * of parts of the network, we also need to support multiple, independent entry
+ * points and this class represents that. 
+ * 
+ * It replaces the function of the Rete Node class in previous designs.
+ * 
+ * @see ObjectTypeNode
+ *
+ * @author <a href="mailto:tirelli at post.com">Edson Tirelli</a>
+ */
+public class EntryPointNode extends ObjectSource
+    implements
+    Serializable,
+    ObjectSink {
+    // ------------------------------------------------------------
+    // Instance members
+    // ------------------------------------------------------------
+
+    private static final long   serialVersionUID = 420L;
+
+    /**
+     * The entry point ID for this node
+     */
+    private final EntryPoint    entryPoint;
+
+    /**
+     * The object type nodes under this node
+     */
+    private final Map<ObjectType, ObjectTypeNode> objectTypeNodes;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    public EntryPointNode(final int id,
+                          final ObjectSource objectSource,
+                          final BuildContext context) {
+        this( id,
+              objectSource,
+              context.getCurrentEntryPoint() ); // irrelevant for this node, since it overrides sink management
+    }
+
+    public EntryPointNode(final int id,
+                          final ObjectSource objectSource,
+                          final EntryPoint entryPoint) {
+        super( id,
+               objectSource,
+               999 ); // irrelevant for this node, since it overrides sink management
+        this.entryPoint = entryPoint;
+        this.objectTypeNodes = new HashMap<ObjectType, ObjectTypeNode>();
+    }
+
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+
+    /**
+     * @return the entryPoint
+     */
+    public EntryPoint getEntryPoint() {
+        return entryPoint;
+    }
+
+    /**
+     * This is the entry point into the network for all asserted Facts. Iterates a cache
+     * of matching <code>ObjectTypdeNode</code>s asserting the Fact. If the cache does not
+     * exist it first iterates and builds the cache.
+     *
+     * @param handle
+     *            The FactHandle of the fact to assert
+     * @param context
+     *            The <code>PropagationContext</code> of the <code>WorkingMemory</code> action
+     * @param workingMemory
+     *            The working memory session.
+     */
+    public void assertObject(final InternalFactHandle handle,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+
+        ObjectTypeConf objectTypeConf = workingMemory.getObjectTypeConf( this.entryPoint,
+                                                                         handle.getObject() );
+
+        // checks if shadow is enabled
+        if ( objectTypeConf.isShadowEnabled() ) {
+            // need to improve this
+            if ( !(handle.getObject() instanceof ShadowProxy) ) {
+                // replaces the actual object by its shadow before propagating
+                handle.setObject( objectTypeConf.getShadow( handle.getObject() ) );
+                handle.setShadowFact( true );
+            } else {
+                ((ShadowProxy) handle.getObject()).updateProxy();
+            }
+        }
+
+        ObjectTypeNode[] cachedNodes = objectTypeConf.getObjectTypeNodes();
+
+        for ( int i = 0, length = cachedNodes.length; i < length; i++ ) {
+            cachedNodes[i].assertObject( handle,
+                                         context,
+                                         workingMemory );
+        }
+    }
+
+    /**
+     * Retract a fact object from this <code>RuleBase</code> and the specified
+     * <code>WorkingMemory</code>.
+     *
+     * @param handle
+     *            The handle of the fact to retract.
+     * @param workingMemory
+     *            The working memory session.
+     */
+    public void retractObject(final InternalFactHandle handle,
+                              final PropagationContext context,
+                              final InternalWorkingMemory workingMemory) {
+        final Object object = handle.getObject();
+
+        ObjectTypeConf objectTypeConf = workingMemory.getObjectTypeConf( this.entryPoint,
+                                                                         object );
+        ObjectTypeNode[] cachedNodes = objectTypeConf.getObjectTypeNodes();
+
+        if ( cachedNodes == null ) {
+            // it is  possible that there are no ObjectTypeNodes for an  object being retracted
+            return;
+        }
+
+        for ( int i = 0; i < cachedNodes.length; i++ ) {
+            cachedNodes[i].retractObject( handle,
+                                          context,
+                                          workingMemory );
+        }
+    }
+
+    /**
+     * Adds the <code>ObjectSink</code> so that it may receive
+     * <code>Objects</code> propagated from this <code>ObjectSource</code>.
+     *
+     * @param objectSink
+     *            The <code>ObjectSink</code> to receive propagated
+     *            <code>Objects</code>. Rete only accepts <code>ObjectTypeNode</code>s
+     *            as parameters to this method, though.
+     */
+    protected void addObjectSink(final ObjectSink objectSink) {
+        final ObjectTypeNode node = (ObjectTypeNode) objectSink;
+        this.objectTypeNodes.put( node.getObjectType(),
+                                  node );
+    }
+
+    protected void removeObjectSink(final ObjectSink objectSink) {
+        final ObjectTypeNode node = (ObjectTypeNode) objectSink;
+        this.objectTypeNodes.remove( node.getObjectType() );
+    }
+
+    public void attach() {
+        this.objectSource.addObjectSink( this );
+    }
+
+    public void attach(final InternalWorkingMemory[] workingMemories) {
+        attach();
+
+        for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+            final InternalWorkingMemory workingMemory = workingMemories[i];
+            final PropagationContext propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
+                                                                                      PropagationContext.RULE_ADDITION,
+                                                                                      null,
+                                                                                      null );
+            this.objectSource.updateSink( this,
+                                          propagationContext,
+                                          workingMemory );
+        }
+    }
+
+    public void remove(ReteooBuilder builder,
+                       final BaseNode node, final InternalWorkingMemory[] workingMemories) {
+        final ObjectTypeNode objectTypeNode = (ObjectTypeNode) node;
+        removeObjectSink( objectTypeNode );
+        for ( int i = 0; i < workingMemories.length; i++ ) {
+            // clear the node memory for each working memory.
+            workingMemories[i].clearNodeMemory( (NodeMemory) node );
+        }
+    }
+
+    public Map<ObjectType, ObjectTypeNode> getObjectTypeNodes() {
+        return this.objectTypeNodes;
+    }
+
+    public int hashCode() {
+        return this.entryPoint.hashCode();
+    }
+
+    public boolean equals(final Object object) {
+        if ( object == this ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof EntryPointNode) ) {
+            return false;
+        }
+
+        final EntryPointNode other = (EntryPointNode) object;
+        return this.entryPoint.equals( other.entryPoint );
+    }
+
+    public void updateSink(final ObjectSink sink,
+                           final PropagationContext context,
+                           final InternalWorkingMemory workingMemory) {
+        // JBRULES-612: the cache MUST be invalidated when a new node type is added to the network, so iterate and reset all caches.
+        final ObjectTypeNode node = (ObjectTypeNode) sink;
+        final ObjectType newObjectType = node.getObjectType();
+
+        for ( ObjectTypeConf objectTypeConf : workingMemory.getObjectTypeConfMap( this.entryPoint ).values() ) {
+            if ( newObjectType.isAssignableFrom( objectTypeConf.getConcreteObjectTypeNode().getObjectType() ) ) {
+                objectTypeConf.resetCache();
+                ObjectTypeNode sourceNode = objectTypeConf.getConcreteObjectTypeNode();
+                FactHashTable table = (FactHashTable) workingMemory.getNodeMemory( sourceNode );
+                Iterator factIter = table.iterator();
+                for ( FactEntry factEntry = (FactEntry) factIter.next(); factEntry != null; factEntry = (FactEntry) factIter.next() ) {
+                    sink.assertObject( factEntry.getFactHandle(),
+                                       context,
+                                       workingMemory );
+                }
+            }
+        }
+    }
+
+    public boolean isObjectMemoryEnabled() {
+        return false;
+    }
+
+    public void setObjectMemoryEnabled(boolean objectMemoryEnabled) {
+        throw new UnsupportedOperationException( "Entry Point Node has no Object memory" );
+    }
+    
+    public String toString() {
+        return "[EntryPointNode("+this.id+") "+this.entryPoint+" ]";
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/EvalConditionNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/EvalConditionNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/EvalConditionNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,282 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.RuleBaseConfiguration;
+import org.drools.common.BaseNode;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.NodeMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.EvalCondition;
+import org.drools.spi.PropagationContext;
+import org.drools.util.Iterator;
+import org.drools.util.TupleHashTable;
+
+/**
+ * Node which filters <code>ReteTuple</code>s.
+ * 
+ * <p>
+ * Using a semantic <code>Test</code>, this node may allow or disallow
+ * <code>Tuples</code> to proceed further through the Rete-OO network.
+ * </p>
+ * 
+ * @see EvalConditionNode
+ * @see Eval
+ * @see ReteTuple
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ */
+public class EvalConditionNode extends TupleSource
+    implements
+    TupleSinkNode,
+    NodeMemory {
+    // ------------------------------------------------------------
+    // Instance members
+    // ------------------------------------------------------------
+
+    /**
+     * 
+     */
+    private static final long   serialVersionUID = 400L;
+
+    /** The semantic <code>Test</code>. */
+    private final EvalCondition condition;
+
+    /** The source of incoming <code>Tuples</code>. */
+    private final TupleSource   tupleSource;
+    
+    protected boolean          tupleMemoryEnabled;        
+
+    private TupleSinkNode       previousTupleSinkNode;
+    private TupleSinkNode       nextTupleSinkNode;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    /**
+     * Construct.
+     * 
+     * @param rule
+     *            The rule
+     * @param tupleSource
+     *            The source of incoming <code>Tuples</code>.
+     * @param eval
+     */
+    public EvalConditionNode(final int id,
+                             final TupleSource tupleSource,
+                             final EvalCondition eval,
+                             final BuildContext context) {
+        super( id );
+        this.condition = eval;
+        this.tupleSource = tupleSource;
+        this.tupleMemoryEnabled = context.isTupleMemoryEnabled();
+    }
+
+    /**
+     * Attaches this node into the network.
+     */
+    public void attach() {
+        this.tupleSource.addTupleSink( this );
+    }
+
+    public void attach(final InternalWorkingMemory[] workingMemories) {
+        attach();
+
+        for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+            final InternalWorkingMemory workingMemory = workingMemories[i];
+            final PropagationContext propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
+                                                                                      PropagationContext.RULE_ADDITION,
+                                                                                      null,
+                                                                                      null );
+            this.tupleSource.updateSink( this,
+                                         propagationContext,
+                                         workingMemory );
+        }
+    }
+
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+
+    /**
+     * Retrieve the <code>Test</code> associated with this node.
+     * 
+     * @return The <code>Test</code>.
+     */
+    public EvalCondition getCondition() {
+        return this.condition;
+    }
+
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // org.drools.reteoo.impl.TupleSink
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+    /**
+     * Assert a new <code>Tuple</code>.
+     * 
+     * @param tuple
+     *            The <code>Tuple</code> being asserted.
+     * @param workingMemory
+     *            The working memory seesion.
+     * @throws AssertionException
+     *             If an error occurs while asserting.
+     */
+    public void assertTuple(final ReteTuple tuple,
+                            final PropagationContext context,
+                            final InternalWorkingMemory workingMemory) {
+
+        final boolean allowed = this.condition.isAllowed( tuple,
+                                                          workingMemory );
+
+        if ( allowed ) {
+            if ( this.tupleMemoryEnabled ) {
+                final TupleHashTable memory = (TupleHashTable) workingMemory.getNodeMemory( this );
+                memory.add( tuple );
+            }
+
+            this.sink.propagateAssertTuple( tuple,
+                                            context,
+                                            workingMemory );
+        }
+    }
+
+    public void retractTuple(final ReteTuple tuple,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+        final TupleHashTable memory = (TupleHashTable) workingMemory.getNodeMemory( this );
+
+        // can we improve that?
+        final ReteTuple memTuple = memory.remove( tuple );
+        if ( memTuple != null ) {
+            this.sink.propagateRetractTuple( memTuple,
+                                             context,
+                                             workingMemory );
+        }
+    }
+
+    /**
+     * Produce a debug string.
+     * 
+     * @return The debug string.
+     */
+    public String toString() {
+        return "[EvalConditionNode: cond=" + this.condition + "]";
+    }
+
+    public int hashCode() {
+        return this.tupleSource.hashCode() ^ this.condition.hashCode();
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || object.getClass() != EvalConditionNode.class ) {
+            return false;
+        }
+
+        final EvalConditionNode other = (EvalConditionNode) object;
+
+        return this.tupleSource.equals( other.tupleSource ) && this.condition.equals( other.condition );
+    }
+
+    public Object createMemory(final RuleBaseConfiguration config) {
+        return new TupleHashTable();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.BaseNode#updateNewNode(org.drools.reteoo.WorkingMemoryImpl, org.drools.spi.PropagationContext)
+     */
+    public void updateSink(final TupleSink sink,
+                           final PropagationContext context,
+                           final InternalWorkingMemory workingMemory) {
+
+        final TupleHashTable memory = (TupleHashTable) workingMemory.getNodeMemory( this );
+
+        final Iterator it = memory.iterator();
+        for ( ReteTuple tuple = (ReteTuple) it.next(); tuple != null; tuple = (ReteTuple) it.next() ) {
+            sink.assertTuple( tuple,
+                              context,
+                              workingMemory );
+        }
+    }
+
+    public void remove(ReteooBuilder builder,
+                       final BaseNode node, final InternalWorkingMemory[] workingMemories) {
+        if ( !node.isInUse() ) {
+            removeTupleSink( (TupleSink) node );
+        }
+        removeShare(builder);
+        if ( !this.isInUse() ) {
+            for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+                workingMemories[i].clearNodeMemory( this );
+            }
+        }
+        this.tupleSource.remove( builder,
+                                 this, workingMemories );
+
+    }
+    
+    public boolean isTupleMemoryEnabled() {
+        return tupleMemoryEnabled;
+    }
+
+    public void setTupleMemoryEnabled(boolean tupleMemoryEnabled) {
+        this.tupleMemoryEnabled = tupleMemoryEnabled;
+    }      
+
+    /**
+     * Returns the next node
+     * @return
+     *      The next TupleSinkNode
+     */
+    public TupleSinkNode getNextTupleSinkNode() {
+        return this.nextTupleSinkNode;
+    }
+
+    /**
+     * Sets the next node 
+     * @param next
+     *      The next TupleSinkNode
+     */
+    public void setNextTupleSinkNode(final TupleSinkNode next) {
+        this.nextTupleSinkNode = next;
+    }
+
+    /**
+     * Returns the previous node
+     * @return
+     *      The previous TupleSinkNode
+     */
+    public TupleSinkNode getPreviousTupleSinkNode() {
+        return this.previousTupleSinkNode;
+    }
+
+    /**
+     * Sets the previous node 
+     * @param previous
+     *      The previous TupleSinkNode
+     */
+    public void setPreviousTupleSinkNode(final TupleSinkNode previous) {
+        this.previousTupleSinkNode = previous;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ExistsNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ExistsNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ExistsNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2006 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;
+
+import org.drools.common.BetaConstraints;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.spi.PropagationContext;
+import org.drools.util.FactEntry;
+import org.drools.util.Iterator;
+
+/**
+ * <code>ExistsNode</code> extends <code>BetaNode</code> to perform tests for
+ * the existence of a Fact plus one or more conditions. Where existence
+ * is found the left ReteTuple is copied and propagated. Further to this it
+ * maintains the "truth" by canceling any
+ * <code>Activation<code>s that are no longer 
+ * considered true by the retraction of ReteTuple's or FactHandleImpl.  
+ * Tuples are considered to be asserted from the left input and facts from the right input.
+ * The <code>BetaNode</code> provides the BetaMemory to store asserted ReteTuples and 
+ * <code>FactHandleImpl<code>s. Each fact handle is stored in the right 
+ * memory.
+ * 
+ * @author <a href="mailto:etirelli at redhat.com">Edson Tirelli</a>
+ *
+ */
+public class ExistsNode extends BetaNode {
+
+    private static final long serialVersionUID = 400L;
+
+    static int                notAssertObject  = 0;
+    static int                notAssertTuple   = 0;
+
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+
+    /**
+     * Construct.
+     * 
+     * @param id
+     *            The unique id for this node.
+     * @param leftInput
+     *            The left input <code>TupleSource</code>.
+     * @param rightInput
+     *            The right input <code>ObjectSource</code>.
+     * @param joinNodeBinder
+     *            The constraints to be applied to the right objects
+     */
+    public ExistsNode(final int id,
+                      final TupleSource leftInput,
+                      final ObjectSource rightInput,
+                      final BetaConstraints joinNodeBinder,
+                      final BuildContext context) {
+        super( id,
+               leftInput,
+               rightInput,
+               joinNodeBinder );
+        this.tupleMemoryEnabled = context.isTupleMemoryEnabled();        
+    }
+
+    /**
+     * Assert a new <code>ReteTuple</code> from the left input. It iterates
+     * over the right <code>FactHandleImpl</code>'s and if any match is found,
+     * a copy of the <code>ReteTuple</code> is made and propagated.
+     * 
+     * @param tuple
+     *            The <code>Tuple</code> being asserted.
+     * @param context
+     *            The <code>PropagationContext</code>
+     * @param workingMemory
+     *            The working memory session.
+     */
+    public void assertTuple(final ReteTuple leftTuple,
+                            final PropagationContext context,
+                            final InternalWorkingMemory workingMemory) {
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+        
+        if ( this.tupleMemoryEnabled ) {
+            memory.getTupleMemory().add( leftTuple );
+        }
+
+        final Iterator it = memory.getFactHandleMemory().iterator( leftTuple );
+        this.constraints.updateFromTuple( workingMemory,
+                                          leftTuple );
+        for ( FactEntry entry = (FactEntry) it.next(); entry != null; entry = (FactEntry) it.next() ) {            
+            final InternalFactHandle handle = entry.getFactHandle();
+            if ( this.constraints.isAllowedCachedLeft( handle ) ) {
+                leftTuple.setMatch( handle );
+                break;
+            }            
+        }
+        
+        this.constraints.resetTuple();
+
+        if ( leftTuple.getMatch() != null ) {
+            this.sink.propagateAssertTuple( leftTuple,
+                                            context,
+                                            workingMemory );
+        }
+    }
+
+    /**
+     * Assert a new <code>FactHandleImpl</code> from the right input. If it
+     * matches any left ReteTuple's that had no matches before, propagate 
+     * tuple as an assertion.
+     * 
+     * @param handle
+     *            The <code>FactHandleImpl</code> being asserted.
+     * @param context
+     *            The <code>PropagationContext</code>
+     * @param workingMemory
+     *            The working memory session.
+     */
+    public void assertObject(final InternalFactHandle handle,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+        memory.getFactHandleMemory().add( handle );
+        
+        if ( !this.tupleMemoryEnabled ) {
+            // do nothing here, as we know there are no left tuples at this stage in sequential mode.
+            return;
+        }          
+
+        final Iterator it = memory.getTupleMemory().iterator( handle );
+        this.constraints.updateFromFactHandle( workingMemory,
+                                               handle );
+        for ( ReteTuple tuple = (ReteTuple) it.next(); tuple != null; tuple = (ReteTuple) it.next() ) {
+            if ( this.constraints.isAllowedCachedRight( tuple ) && tuple.getMatch() == null) {
+                    tuple.setMatch( handle );
+                    this.sink.propagateAssertTuple( tuple,
+                                                     context,
+                                                     workingMemory );                                 
+            }
+        }
+        
+        this.constraints.resetFactHandle();
+    }
+
+    /**
+     * Retract the <code>FactHandleImpl</code>. If the handle has any
+     * <code>ReteTuple</code> matches and those tuples now have no
+     * other match, retract tuple
+     * 
+     * @param handle
+     *            the <codeFactHandleImpl</code> being retracted
+     * @param context
+     *            The <code>PropagationContext</code>
+     * @param workingMemory
+     *            The working memory session.
+     */
+    public void retractObject(final InternalFactHandle handle,
+                              final PropagationContext context,
+                              final InternalWorkingMemory workingMemory) {
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+        if ( !memory.getFactHandleMemory().remove( handle ) ) {
+            return;
+        }
+
+        final Iterator it = memory.getTupleMemory().iterator( handle );
+        this.constraints.updateFromFactHandle( workingMemory,
+                                               handle );
+        for ( ReteTuple tuple = (ReteTuple) it.next(); tuple != null; tuple = (ReteTuple) it.next() ) {
+            if ( this.constraints.isAllowedCachedRight( tuple ) ) {
+                if ( tuple.getMatch() == handle ) {
+                    // reset the match                    
+                    tuple.setMatch( null );
+                    
+                    // find next match, remember it and break.
+                    final Iterator tupleIt = memory.getFactHandleMemory().iterator( tuple );
+                    this.constraints.updateFromTuple( workingMemory, tuple );
+                    
+                    for ( FactEntry entry = (FactEntry) tupleIt.next(); entry != null; entry = (FactEntry) tupleIt.next() ) {
+                        final InternalFactHandle rightHandle = entry.getFactHandle();
+                        if ( this.constraints.isAllowedCachedLeft( rightHandle ) ) {
+                            tuple.setMatch( rightHandle );
+                            break;
+                        }
+                    }
+                    
+                    this.constraints.resetTuple();
+                    
+                    // if there is now no new tuple match then propagate assert.
+                    if ( tuple.getMatch() == null ) {
+                        this.sink.propagateRetractTuple( tuple,
+                                                        context,
+                                                        workingMemory );
+                    }                    
+                }
+                
+            }
+        }
+
+        this.constraints.resetFactHandle();
+    }
+
+    /**
+     * Retract the
+     * <code>ReteTuple<code>, any resulting propagated joins are also retracted. 
+     * 
+     * @param leftTuple
+     *            The tuple being retracted
+     * @param context
+     *            The <code>PropagationContext</code>
+     * @param workingMemory
+     *            The working memory session.
+     */
+    public void retractTuple(final ReteTuple leftTuple,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+
+        // Must use the tuple in memory as it has the tuple matches count
+        final ReteTuple tuple = memory.getTupleMemory().remove( leftTuple );
+        if ( tuple == null ) {
+            return;
+        }
+
+        if ( tuple.getMatch() !=  null) {
+            this.sink.propagateRetractTuple( tuple,
+                                             context,
+                                             workingMemory );
+        }
+    }
+
+    /**
+     * Updates the given sink propagating all previously propagated tuples to it
+     * 
+     */
+    public void updateSink(final TupleSink sink,
+                           final PropagationContext context,
+                           final InternalWorkingMemory workingMemory) {
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+
+        final Iterator tupleIter = memory.getTupleMemory().iterator();
+        for ( ReteTuple tuple = (ReteTuple) tupleIter.next(); tuple != null; tuple = (ReteTuple) tupleIter.next() ) {
+            if ( tuple.getMatch() != null ) {
+                sink.assertTuple( new ReteTuple( tuple ),
+                                  context,
+                                  workingMemory );
+            }
+        }
+    }
+
+    public String toString() {
+        ObjectSource source = this.rightInput;
+        while ( source.getClass() != ObjectTypeNode.class ) {
+            source = source.objectSource;
+        }
+
+        return "[ExistsNode - " + ((ObjectTypeNode) source).getObjectType() + "]";
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/FactHandleMemory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/FactHandleMemory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/FactHandleMemory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,28 @@
+package org.drools.reteoo;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.util.Iterator;
+
+public interface FactHandleMemory {
+    public Iterator iterator();
+
+    public Iterator iterator(ReteTuple tuple);
+
+    public boolean add(InternalFactHandle handle,
+                       boolean checkExists);
+
+    public boolean add(InternalFactHandle handle);
+
+    public boolean remove(InternalFactHandle handle);
+
+    public boolean contains(InternalFactHandle handle);
+    
+    public InternalFactHandle peek();
+
+    public boolean isIndexed();
+
+    public int size();
+
+//    public Entry[] getTable();
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/FactTemplateTypeConf.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/FactTemplateTypeConf.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/FactTemplateTypeConf.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Nov 26, 2007
+ */
+package org.drools.reteoo;
+
+import java.io.Serializable;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.common.InternalRuleBase;
+import org.drools.facttemplates.FactTemplate;
+import org.drools.facttemplates.FactTemplateObjectType;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.reteoo.builder.PatternBuilder;
+import org.drools.rule.EntryPoint;
+import org.drools.spi.ObjectType;
+
+public class FactTemplateTypeConf
+    implements
+    ObjectTypeConf,
+    Serializable {
+
+    private static final long serialVersionUID = 4493660262148247467L;
+
+    private FactTemplate     factTemplate;
+    private ObjectTypeNode   concreteObjectTypeNode;
+    private ObjectTypeNode[] cache;
+
+    public FactTemplateTypeConf(final EntryPoint entryPoint,
+                                final FactTemplate factTemplate,
+                                final InternalRuleBase ruleBase) {
+        this.factTemplate = factTemplate;
+
+        ObjectType objectType = new FactTemplateObjectType( factTemplate );
+        this.concreteObjectTypeNode = (ObjectTypeNode) ruleBase.getRete().getObjectTypeNodes( entryPoint ).get( objectType );
+        if ( this.concreteObjectTypeNode == null ) {
+            BuildContext context = new BuildContext( ruleBase,
+                                                     ((ReteooRuleBase) ruleBase.getRete().getRuleBase()).getReteooBuilder().getIdGenerator() );
+            if ( context.getRuleBase().getConfiguration().isSequential() ) {
+                // We are in sequential mode, so no nodes should have memory
+                context.setTupleMemoryEnabled( false );
+                context.setObjectTypeNodeMemoryEnabled( false );
+                context.setTerminalNodeMemoryEnabled( false );
+            } else {
+                context.setTupleMemoryEnabled( true );
+                context.setObjectTypeNodeMemoryEnabled( true );
+                context.setTerminalNodeMemoryEnabled( true );
+            }
+            // there must exist an ObjectTypeNode for this concrete class                
+            this.concreteObjectTypeNode = PatternBuilder.attachObjectTypeNode( context,
+                                                                               objectType );
+        }
+        this.cache = new ObjectTypeNode[]{this.concreteObjectTypeNode};
+    }
+
+    public ObjectTypeNode getConcreteObjectTypeNode() {
+        return this.concreteObjectTypeNode;
+    }
+
+    public ObjectTypeNode[] getObjectTypeNodes() {
+        if ( this.cache == null ) {
+            this.cache = new ObjectTypeNode[]{this.concreteObjectTypeNode};
+        }
+        return this.cache;
+    }
+
+    public Object getShadow(Object fact) throws RuntimeDroolsException {
+        return null;
+    }
+
+    public boolean isShadowEnabled() {
+        return false;
+    }
+
+    public boolean isAssignableFrom(Object object) {
+        return this.factTemplate.equals( object );
+    }
+
+    public void resetCache() {
+        this.cache = null;
+    }
+
+    public boolean isActive() {
+        return true;
+    }
+
+    public boolean isEvent() {
+        return false;
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/FromNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/FromNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/FromNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,234 @@
+package org.drools.reteoo;
+
+import org.drools.RuleBaseConfiguration;
+import org.drools.common.BaseNode;
+import org.drools.common.BetaConstraints;
+import org.drools.common.EmptyBetaConstraints;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.NodeMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.DataProvider;
+import org.drools.spi.PropagationContext;
+import org.drools.util.Iterator;
+import org.drools.util.LinkedList;
+import org.drools.util.LinkedListEntry;
+import org.drools.util.TupleHashTable;
+
+public class FromNode extends TupleSource
+    implements
+    TupleSinkNode,
+    NodeMemory {
+    /**
+     * 
+     */
+    private static final long          serialVersionUID = 400L;
+
+    private DataProvider               dataProvider;
+    private TupleSource                tupleSource;
+    private AlphaNodeFieldConstraint[] alphaConstraints;
+    private BetaConstraints            betaConstraints;
+
+    private TupleSinkNode              previousTupleSinkNode;
+    private TupleSinkNode              nextTupleSinkNode;
+    
+    protected boolean                 tupleMemoryEnabled;      
+
+    public FromNode(final int id,
+                    final DataProvider dataProvider,
+                    final TupleSource tupleSource,
+                    final AlphaNodeFieldConstraint[] constraints,
+                    final BetaConstraints binder) {
+        super( id );
+        this.dataProvider = dataProvider;
+        this.tupleSource = tupleSource;
+        this.alphaConstraints = constraints;
+        this.betaConstraints = (binder == null) ? EmptyBetaConstraints.getInstance() : binder;
+        this.tupleMemoryEnabled = false;
+    }
+
+    /**
+     * @inheritDoc 
+     */
+    public void assertTuple(final ReteTuple leftTuple,
+                            final PropagationContext context,
+                            final InternalWorkingMemory workingMemory) {
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+
+        memory.getTupleMemory().add( leftTuple );
+        final LinkedList list = new LinkedList();
+        this.betaConstraints.updateFromTuple( workingMemory,
+                                              leftTuple );
+
+        for ( final java.util.Iterator it = this.dataProvider.getResults( leftTuple,
+                                                                          workingMemory,
+                                                                          context ); it.hasNext(); ) {
+            final Object object = it.next();
+
+            final InternalFactHandle handle = workingMemory.getFactHandleFactory().newFactHandle( object, false, workingMemory );
+
+            boolean isAllowed = true;
+            if ( this.alphaConstraints != null ) {
+                // First alpha node filters
+                for ( int i = 0, length = this.alphaConstraints.length; i < length; i++ ) {
+                    if ( !this.alphaConstraints[i].isAllowed( handle,
+                                                              workingMemory ) ) {
+                        // next iteration
+                        isAllowed = false;
+                        break;
+                    }
+                }
+            }
+
+            if ( isAllowed && this.betaConstraints.isAllowedCachedLeft( handle ) ) {
+                list.add( new LinkedListEntry( handle ) );
+
+                this.sink.propagateAssertTuple( leftTuple,
+                                                handle,
+                                                context,
+                                                workingMemory );
+            } else {
+                workingMemory.getFactHandleFactory().destroyFactHandle( handle );
+            }
+        }
+        
+        this.betaConstraints.resetTuple();
+        
+        if ( !list.isEmpty() ) {
+            memory.getCreatedHandles().put( leftTuple,
+                                            list );
+        }
+
+    }
+
+    public void retractTuple(final ReteTuple leftTuple,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+        final ReteTuple tuple = memory.getTupleMemory().remove( leftTuple );
+
+        final LinkedList list = (LinkedList) memory.getCreatedHandles().remove( tuple );
+        // if tuple was propagated
+        if ( list != null ) {
+            for ( LinkedListEntry entry = (LinkedListEntry) list.getFirst(); entry != null; entry = (LinkedListEntry) entry.getNext() ) {
+                final InternalFactHandle handle = (InternalFactHandle) entry.getObject();
+                this.sink.propagateRetractTuple( leftTuple,
+                                                 handle,
+                                                 context,
+                                                 workingMemory );
+                workingMemory.getFactHandleFactory().destroyFactHandle( handle );
+            }
+        }
+    }
+
+    public void attach() {
+        this.tupleSource.addTupleSink( this );
+    }
+
+    public void attach(final InternalWorkingMemory[] workingMemories) {
+        attach();
+
+        for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+            final InternalWorkingMemory workingMemory = workingMemories[i];
+            final PropagationContext propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
+                                                                                      PropagationContext.RULE_ADDITION,
+                                                                                      null,
+                                                                                      null );
+            this.tupleSource.updateSink( this,
+                                         propagationContext,
+                                         workingMemory );
+        }
+    }
+
+    public void remove(ReteooBuilder builder,
+                       final BaseNode node, final InternalWorkingMemory[] workingMemories) {
+
+        if ( !node.isInUse() ) {
+            removeTupleSink( (TupleSink) node );
+        }
+        removeShare(builder);
+
+        if ( !this.isInUse() ) {
+            for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+                workingMemories[i].clearNodeMemory( this );
+            }
+        }
+        this.tupleSource.remove( builder,
+                                 this, workingMemories );
+    }
+
+    public void updateSink(final TupleSink sink,
+                           final PropagationContext context,
+                           final InternalWorkingMemory workingMemory) {
+
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+
+        final Iterator tupleIter = memory.getTupleMemory().iterator();
+        for ( ReteTuple tuple = (ReteTuple) tupleIter.next(); tuple != null; tuple = (ReteTuple) tupleIter.next() ) {
+            final LinkedList list = (LinkedList) memory.getCreatedHandles().remove( tuple );
+            if ( list == null ) {
+                continue;
+            }
+            for ( LinkedListEntry entry = (LinkedListEntry) list.getFirst(); entry != null; entry = (LinkedListEntry) entry.getNext() ) {
+                final InternalFactHandle handle = (InternalFactHandle) entry.getObject();
+                this.sink.propagateRetractTuple( tuple,
+                                                 handle,
+                                                 context,
+                                                 workingMemory );
+                workingMemory.getFactHandleFactory().destroyFactHandle( handle );
+            }
+        }
+    }
+
+    public Object createMemory(final RuleBaseConfiguration config) {
+        return new BetaMemory( new TupleHashTable(),
+                               null );
+    }
+    
+    public boolean isTupleMemoryEnabled() {
+        return tupleMemoryEnabled;
+    }
+
+    public void setTupleMemoryEnabled(boolean tupleMemoryEnabled) {
+        this.tupleMemoryEnabled = tupleMemoryEnabled;
+    }    
+
+    /**
+     * Returns the next node
+     * @return
+     *      The next TupleSinkNode
+     */
+    public TupleSinkNode getNextTupleSinkNode() {
+        return this.nextTupleSinkNode;
+    }
+
+    /**
+     * Sets the next node 
+     * @param next
+     *      The next TupleSinkNode
+     */
+    public void setNextTupleSinkNode(final TupleSinkNode next) {
+        this.nextTupleSinkNode = next;
+    }
+
+    /**
+     * Returns the previous node
+     * @return
+     *      The previous TupleSinkNode
+     */
+    public TupleSinkNode getPreviousTupleSinkNode() {
+        return this.previousTupleSinkNode;
+    }
+
+    /**
+     * Sets the previous node 
+     * @param previous
+     *      The previous TupleSinkNode
+     */
+    public void setPreviousTupleSinkNode(final TupleSinkNode previous) {
+        this.previousTupleSinkNode = previous;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/InitialFactHandle.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/InitialFactHandle.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/InitialFactHandle.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,91 @@
+package org.drools.reteoo;
+
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class InitialFactHandle extends DefaultFactHandle {
+    /**
+     * 
+     */
+    private static final long        serialVersionUID = 400L;
+
+    private final InternalFactHandle delegate;
+
+    private Object                   object;
+
+    public InitialFactHandle(final InternalFactHandle delegate) {
+        super();
+        this.delegate = delegate;
+        this.object = InitialFactImpl.getInstance();
+    }
+
+    // ----------------------------------------------------------------------
+    // Instance members
+    // ----------------------------------------------------------------------
+
+    /**
+     * @see Object
+     */
+    public boolean equals(final Object object) {
+        return this.delegate.equals( object );
+    }
+
+    /**
+     * @see Object
+     */
+    public int hashCode() {
+        return this.delegate.hashCode();
+    }
+
+    /**
+     * @see Object
+     */
+    public String toString() {
+        return toExternalForm();
+    }
+
+    public long getRecency() {
+        return this.delegate.getRecency();
+    }
+
+    public void setRecency(final long recency) {
+        this.delegate.setRecency( recency );
+    }
+
+    public long getId() {
+        return this.delegate.getId();
+    }
+
+    public void invalidate() {
+        this.delegate.invalidate();
+    }
+
+    public Object getObject() {
+        return this.object;
+    }
+
+    public void setObject(final Object object) {
+        // do nothign
+    }
+
+    public String toExternalForm() {
+        return "InitialFact";
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/InitialFactImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/InitialFactImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/InitialFactImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,58 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.InitialFact;
+
+/**
+ * We dont want users to be able to instantiate InitialFact so we expose it as
+ * an interface and make the class and its constructor package protected
+ *
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ *
+ */
+final class InitialFactImpl
+    implements
+    InitialFact {
+    private static final InitialFact INSTANCE = new InitialFactImpl();
+
+    private final int                hashCode = "InitialFactImpl".hashCode();
+
+    public static InitialFact getInstance() {
+        return InitialFactImpl.INSTANCE;
+    }
+
+    private InitialFactImpl() {
+    }
+
+    public int hashCode() {
+        return this.hashCode;
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof InitialFactImpl) ) {
+            return false;
+        }
+
+        return true;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/JoinNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/JoinNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/JoinNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,267 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.common.BetaConstraints;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.spi.PropagationContext;
+import org.drools.util.FactEntry;
+import org.drools.util.Iterator;
+
+/**
+ * <code>JoinNode</code> extends <code>BetaNode</code> to perform
+ * <code>ReteTuple</code> and <code>FactHandle</code> joins. Tuples are
+ * considered to be asserted from the left input and facts from the right input.
+ * The <code>BetaNode</code> provides the BetaMemory to store assserted
+ * ReteTuples and
+ * <code>FactHandleImpl<code>s. Each fact handle is stored in the right memory as a key in a <code>HashMap</code>, the value is an <code>ObjectMatches</code> 
+ * instance which maintains a <code>LinkedList of <code>TuplesMatches - The tuples that are matched with the handle. the left memory is a <code>LinkedList</code> 
+ * of <code>ReteTuples</code> which maintains a <code>HashMa</code>, where the keys are the matching <code>FactHandleImpl</code>s and the value is 
+ * populated <code>TupleMatche</code>es, the keys are matched fact handles. <code>TupleMatch</code> maintains a <code>List</code> of resulting joins, 
+ * where there is joined <code>ReteTuple</code> per <code>TupleSink</code>.
+ *  
+ * 
+ * The BetaNode provides
+ * the BetaMemory which stores the 
+ * 
+ * @see BetaNode
+ * @see ObjectMatches
+ * @see TupleMatch
+ * @see TupleSink
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ *
+ */
+public class JoinNode extends BetaNode {
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+    
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    public JoinNode(final int id,
+                    final TupleSource leftInput,
+                    final ObjectSource rightInput,
+                    final BetaConstraints binder,
+                    final BuildContext context) {
+        super( id,
+               leftInput,
+               rightInput,
+               binder );
+        tupleMemoryEnabled = context.isTupleMemoryEnabled();
+    }
+
+    /**
+     * Assert a new <code>ReteTuple</code>. The right input of
+     * <code>FactHandleInput</code>'s is iterated and joins attemped, via the
+     * binder, any successful bindings results in joined tuples being created
+     * and propaged. there is a joined tuple per TupleSink.
+     * 
+     * @see ReteTuple
+     * @see ObjectMatches
+     * @see TupleSink
+     * @see TupleMatch
+     * 
+     * @param tuple
+     *            The <code>Tuple</code> being asserted.
+     * @param context
+     *            The <code>PropagationContext</code>
+     * @param workingMemory
+     *            The working memory seesion.
+     */
+    public void assertTuple(final ReteTuple leftTuple,
+                            final PropagationContext context,
+                            final InternalWorkingMemory workingMemory) {
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+        
+        if ( this.tupleMemoryEnabled ) {
+            memory.getTupleMemory().add( leftTuple );
+        }
+
+        final Iterator it = memory.getFactHandleMemory().iterator( leftTuple );
+        this.constraints.updateFromTuple( workingMemory,
+                                          leftTuple );
+        for ( FactEntry entry = (FactEntry) it.next(); entry != null; entry = (FactEntry) it.next() ) {
+            final InternalFactHandle handle = entry.getFactHandle();
+            if ( this.constraints.isAllowedCachedLeft( handle ) ) {
+                this.sink.propagateAssertTuple( leftTuple,
+                                                handle,
+                                                context,
+                                                workingMemory );
+            }
+        }
+        
+        this.constraints.resetTuple();
+    }
+
+    /**
+     * Assert a new <code>FactHandleImpl</code>. The left input of
+     * <code>ReteTuple</code>s is iterated and joins attemped, via the
+     * binder, any successful bindings results in joined tuples being created
+     * and propaged. there is a joined tuple per TupleSink.
+     * 
+     * @see ReteTuple
+     * @see ObjectMatches
+     * @see TupleSink
+     * @see TupleMatch
+     * 
+     * @param handle
+     *            The <code>FactHandleImpl</code> being asserted.
+     * @param context
+     *            The <code>PropagationContext</code>
+     * @param workingMemory
+     *            The working memory seesion.
+     */
+    public void assertObject(final InternalFactHandle handle,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+
+        memory.getFactHandleMemory().add( handle );
+        if ( ! this.tupleMemoryEnabled ) {
+            // do nothing here, as we know there are no left tuples at this stage in sequential mode.
+            return;
+        }
+
+        final Iterator it = memory.getTupleMemory().iterator( handle );
+        this.constraints.updateFromFactHandle( workingMemory,
+                                               handle );
+        for ( ReteTuple tuple = (ReteTuple) it.next(); tuple != null; tuple = (ReteTuple) it.next() ) {
+            if ( this.constraints.isAllowedCachedRight( tuple ) ) {
+                this.sink.propagateAssertTuple( tuple,
+                                                handle,
+                                                context,
+                                                workingMemory );
+            }
+        }
+        this.constraints.resetFactHandle();
+    }
+
+    /**
+     * Retract a FactHandleImpl. Iterates the referenced TupleMatches stored in
+     * the handle's ObjectMatches retracting joined tuples.
+     * 
+     * @param handle
+     *            the <codeFactHandleImpl</code> being retracted
+     * @param context
+     *            The <code>PropagationContext</code>
+     * @param workingMemory
+     *            The working memory seesion.
+     */
+    public void retractObject(final InternalFactHandle handle,
+                              final PropagationContext context,
+                              final InternalWorkingMemory workingMemory) {
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+        if ( !memory.getFactHandleMemory().remove( handle ) ) {
+            return;
+        }
+
+        final Iterator it = memory.getTupleMemory().iterator( handle );
+        this.constraints.updateFromFactHandle( workingMemory,
+                                               handle );
+        for ( ReteTuple tuple = (ReteTuple) it.next(); tuple != null; tuple = (ReteTuple) it.next() ) {
+            if ( this.constraints.isAllowedCachedRight( tuple ) ) {
+                this.sink.propagateRetractTuple( tuple,
+                                                 handle,
+                                                 context,
+                                                 workingMemory );
+            }
+        }
+        
+        this.constraints.resetFactHandle();
+    }
+
+    /**
+     * Retract a <code>ReteTuple</code>. Iterates the referenced
+     * <code>TupleMatche</code>'s stored in the tuples <code>Map</code>
+     * retracting all joined tuples.
+     * 
+     * @param key
+     *            The tuple key.
+     * @param context
+     *            The <code>PropagationContext</code>
+     * @param workingMemory
+     *            The working memory seesion.
+     */
+    public void retractTuple(final ReteTuple leftTuple,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+        final ReteTuple tuple = memory.getTupleMemory().remove( leftTuple );
+        if ( tuple == null ) {
+            return;
+        }
+
+        final Iterator it = memory.getFactHandleMemory().iterator( leftTuple );
+        this.constraints.updateFromTuple( workingMemory,
+                                          leftTuple );
+        for ( FactEntry entry = (FactEntry) it.next(); entry != null; entry = (FactEntry) it.next() ) {
+            final InternalFactHandle handle = entry.getFactHandle();
+            if ( this.constraints.isAllowedCachedLeft( handle ) ) {
+                this.sink.propagateRetractTuple( leftTuple,
+                                                 handle,
+                                                 context,
+                                                 workingMemory );
+            }
+        }
+        
+        this.constraints.resetTuple();
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.BaseNode#updateNewNode(org.drools.reteoo.WorkingMemoryImpl, org.drools.spi.PropagationContext)
+     */
+    public void updateSink(final TupleSink sink,
+                           final PropagationContext context,
+                           final InternalWorkingMemory workingMemory) {
+
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+
+        final Iterator tupleIter = memory.getTupleMemory().iterator();
+        for ( ReteTuple tuple = (ReteTuple) tupleIter.next(); tuple != null; tuple = (ReteTuple) tupleIter.next() ) {
+            final Iterator objectIter = memory.getFactHandleMemory().iterator( tuple );
+            this.constraints.updateFromTuple( workingMemory,
+                                              tuple );
+            for ( FactEntry entry = (FactEntry) objectIter.next(); entry != null; entry = (FactEntry) objectIter.next() ) {
+                final InternalFactHandle handle = entry.getFactHandle();
+                if ( this.constraints.isAllowedCachedLeft( handle ) ) {
+                    sink.assertTuple( new ReteTuple( tuple,
+                                                     handle ),
+                                      context,
+                                      workingMemory );
+                }
+            }
+            
+            this.constraints.resetTuple();
+        }
+    }
+
+    public String toString() {
+        ObjectSource source = this.rightInput;
+        while ( !(source instanceof ObjectTypeNode) ) {
+            source = source.objectSource;
+        }
+
+        return "[JoinNode - " + ((ObjectTypeNode) source).getObjectType() + "]";
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/LIANodePropagation.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/LIANodePropagation.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/LIANodePropagation.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,26 @@
+package org.drools.reteoo;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+
+public class LIANodePropagation {
+    private final LeftInputAdapterNode node;
+    private final InternalFactHandle handle;
+    private final PropagationContext context;
+    
+    public LIANodePropagation(final LeftInputAdapterNode node,
+                              final InternalFactHandle handle,
+                              final PropagationContext context ) {
+        super();
+        this.node = node;
+        this.handle = handle;
+        this.context = context;
+    }
+    
+    public void doPropagation(InternalWorkingMemory workingMemory) {
+        node.getSinkPropagator().createAndPropagateAssertTuple( handle, context, workingMemory );
+    }
+    
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/LeftInputAdapterNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/LeftInputAdapterNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/LeftInputAdapterNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,304 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.RuleBaseConfiguration;
+import org.drools.common.BaseNode;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.NodeMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.spi.PropagationContext;
+import org.drools.util.FactEntry;
+import org.drools.util.FactHashTable;
+import org.drools.util.Iterator;
+
+/**
+ * All asserting Facts must propagated into the right <code>ObjectSink</code> side of a BetaNode, if this is the first Pattern
+ * then there are no BetaNodes to propagate to. <code>LeftInputAdapter</code> is used to adapt an ObjectSink propagation into a 
+ * <code>TupleSource</code> which propagates a <code>ReteTuple</code> suitable fot the right <code>ReteTuple</code> side 
+ * of a <code>BetaNode</code>.
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ *
+ */
+public class LeftInputAdapterNode extends TupleSource
+    implements
+    ObjectSinkNode,
+    NodeMemory {
+
+    /**
+     * 
+     */
+    private static final long  serialVersionUID = 400L;
+    private final ObjectSource objectSource;
+
+    private ObjectSinkNode     previousObjectSinkNode;
+    private ObjectSinkNode     nextObjectSinkNode;
+    
+    private boolean           objectMemoryEnabled;    
+
+    /**
+     * Constructus a LeftInputAdapterNode with a unique id that receives <code>FactHandle</code> from a 
+     * parent <code>ObjectSource</code> and adds it to a given pattern in the resulting Tuples.
+     * 
+     * @param id
+     *      The unique id of this node in the current Rete network
+     * @param source
+     *      The parent node, where Facts are propagated from
+     * @param binder
+     *      An optional binder to filter out propagations. This binder will exist when
+     *      a predicate is used in the first pattern, for instance
+     */
+    public LeftInputAdapterNode(final int id,
+                                final ObjectSource source,
+                                final BuildContext context) {
+        super( id );
+        this.objectSource = source;
+        //this.constraints = constraints;
+        setObjectMemoryEnabled( false );
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.BaseNode#attach()
+     */
+    public void attach() {
+        this.objectSource.addObjectSink( this );
+    }
+
+    public void attach(final InternalWorkingMemory[] workingMemories) {
+        attach();
+
+        for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+            final InternalWorkingMemory workingMemory = workingMemories[i];
+            final PropagationContext propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
+                                                                                      PropagationContext.RULE_ADDITION,
+                                                                                      null,
+                                                                                      null );
+            this.objectSource.updateSink( this,
+                                          propagationContext,
+                                          workingMemory );
+        }
+    }
+
+    /**
+     * Takes the asserted <code>FactHandleImpl</code> received from the <code>ObjectSource</code> and puts it
+     * in a new <code>ReteTuple</code> before propagating to the <code>TupleSinks</code>
+     * 
+     * @param handle
+     *            The asserted <code>FactHandle/code>.
+     * @param context
+     *             The <code>PropagationContext</code> of the <code>WorkingMemory<code> action.           
+     * @param workingMemory
+     *            the <code>WorkingMemory</code> session.
+     */
+    public void assertObject(final InternalFactHandle handle,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+
+        if ( !workingMemory.isSequential() ) {
+            this.sink.createAndPropagateAssertTuple( handle,
+                                                     context,
+                                                     workingMemory );
+
+            if ( this.objectMemoryEnabled ) {
+                final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( this );
+                memory.add( handle,
+                            false );
+            }
+        } else {
+            workingMemory.addLIANodePropagation( new LIANodePropagation(this, handle, context) );
+        }
+    }
+
+    /**
+     * Retract an existing <code>FactHandleImpl</code> by placing it in a new <code>ReteTuple</code> before 
+     * proagating to the <code>TupleSinks</code>
+     * 
+     * @param handle
+     *            The <code>FactHandle/code> to retract.
+     * @param context
+     *             The <code>PropagationContext</code> of the <code>WorkingMemory<code> action.           
+     * @param workingMemory
+     *            the <code>WorkingMemory</code> session.
+     */
+    public void retractObject(final InternalFactHandle handle,
+                              final PropagationContext context,
+                              final InternalWorkingMemory workingMemory) {
+        boolean propagate = true;
+        if ( this.objectMemoryEnabled ) {
+            final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( this );
+            propagate = memory.remove( handle );
+        }
+
+        if ( propagate ) {
+            this.sink.createAndPropagateRetractTuple( handle,
+                                                      context,
+                                                      workingMemory );
+        }
+    }
+
+    public void updateSink(final TupleSink sink,
+                           final PropagationContext context,
+                           final InternalWorkingMemory workingMemory) {
+        if ( this.objectMemoryEnabled ) {
+            // We have memory so iterate over all entries
+            final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( this );
+            final Iterator it = memory.iterator();
+            for ( FactEntry entry = (FactEntry) it.next(); entry != null; entry = (FactEntry) it.next() ) {
+                final InternalFactHandle handle = entry.getFactHandle();
+                sink.assertTuple( new ReteTuple( handle ),
+                                  context,
+                                  workingMemory );
+            }
+        } else {
+            final ObjectSinkAdapter adapter = new ObjectSinkAdapter( sink );
+            this.objectSource.updateSink( adapter,
+                                          context,
+                                          workingMemory );
+        }
+    }
+
+    public void remove(ReteooBuilder builder,
+                       final BaseNode node, final InternalWorkingMemory[] workingMemories) {
+        if ( !node.isInUse() ) {
+            removeTupleSink( (TupleSink) node );
+        }
+        removeShare(builder);
+        if ( !this.isInUse() ) {
+            for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+                workingMemories[i].clearNodeMemory( this );
+            }
+        }
+        this.objectSource.remove( builder,
+                                  this, workingMemories );
+    }    
+    
+    public boolean isObjectMemoryEnabled() {
+        return this.objectMemoryEnabled;
+    }
+
+    public void setObjectMemoryEnabled(boolean objectMemoryEnabled) {
+        this.objectMemoryEnabled = objectMemoryEnabled;
+    }    
+
+    /**
+     * Returns the next node
+     * @return
+     *      The next ObjectSinkNode
+     */
+    public ObjectSinkNode getNextObjectSinkNode() {
+        return this.nextObjectSinkNode;
+    }
+
+    /**
+     * Sets the next node 
+     * @param next
+     *      The next ObjectSinkNode
+     */
+    public void setNextObjectSinkNode(final ObjectSinkNode next) {
+        this.nextObjectSinkNode = next;
+    }
+
+    /**
+     * Returns the previous node
+     * @return
+     *      The previous ObjectSinkNode
+     */
+    public ObjectSinkNode getPreviousObjectSinkNode() {
+        return this.previousObjectSinkNode;
+    }
+
+    /**
+     * Sets the previous node 
+     * @param previous
+     *      The previous ObjectSinkNode
+     */
+    public void setPreviousObjectSinkNode(final ObjectSinkNode previous) {
+        this.previousObjectSinkNode = previous;
+    }
+
+    public int hashCode() {
+        return this.objectSource.hashCode();
+    }
+
+    public boolean equals(final Object object) {
+        if ( object == this ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof LeftInputAdapterNode) ) {
+            return false;
+        }
+
+        final LeftInputAdapterNode other = (LeftInputAdapterNode) object;
+
+        return this.objectSource.equals( other.objectSource );
+    }
+
+    public Object createMemory(final RuleBaseConfiguration config) {
+        return new FactHashTable();
+    }
+
+    /**
+     * Used with the updateSink method, so that the parent ObjectSource
+     * can  update the  TupleSink
+     * @author mproctor
+     *
+     */
+    private static class ObjectSinkAdapter
+        implements
+        ObjectSink {
+        private TupleSink sink;
+
+        public ObjectSinkAdapter(final TupleSink sink) {
+            this.sink = sink;
+        }
+
+        public void assertObject(final InternalFactHandle handle,
+                                 final PropagationContext context,
+                                 final InternalWorkingMemory workingMemory) {
+            final ReteTuple tuple = new ReteTuple( handle );
+            this.sink.assertTuple( tuple,
+                                   context,
+                                   workingMemory );
+        }
+
+        public void modifyObject(final InternalFactHandle handle,
+                                 final PropagationContext context,
+                                 final InternalWorkingMemory workingMemory) {
+            throw new UnsupportedOperationException( "ObjectSinkAdapter onlys supports assertObject method calls" );
+        }
+
+        public void retractObject(final InternalFactHandle handle,
+                                  final PropagationContext context,
+                                  final InternalWorkingMemory workingMemory) {
+            throw new UnsupportedOperationException( "ObjectSinkAdapter onlys supports assertObject method calls" );
+        }
+        
+        public boolean isObjectMemoryEnabled() {
+            throw new UnsupportedOperationException("ObjectSinkAdapters have no Object memory");
+        }
+
+        public void setObjectMemoryEnabled(boolean objectMemoryEnabled) {
+            throw new UnsupportedOperationException("ObjectSinkAdapters have no Object memory");
+        }        
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/MemoryVisitor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/MemoryVisitor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/MemoryVisitor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,270 @@
+package org.drools.reteoo;
+
+import java.lang.reflect.Field;
+import java.util.Map;
+
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.RuleTerminalNode.TerminalNodeMemory;
+import org.drools.spi.ObjectType;
+import org.drools.util.AbstractHashTable;
+import org.drools.util.Entry;
+import org.drools.util.FactHandleIndexHashTable;
+import org.drools.util.FactHashTable;
+import org.drools.util.ReflectiveVisitor;
+import org.drools.util.FactHandleIndexHashTable.FieldIndexEntry;
+
+public class MemoryVisitor extends ReflectiveVisitor {
+    private InternalWorkingMemory workingMemory;
+    private int                   indent = 0;
+
+    /**
+     * Constructor.
+     */
+    public MemoryVisitor(final InternalWorkingMemory workingMemory) {
+        this.workingMemory = workingMemory;
+    }
+
+    /**
+     * RuleBaseImpl visits its Rete.
+     */
+    public void visitReteooRuleBase(final ReteooRuleBase ruleBase) {
+        visit( (ruleBase).getRete() );
+    }
+
+    /**
+     * Rete visits each of its ObjectTypeNodes.
+     */
+    public void visitRete(final Rete rete) {
+        for( ObjectTypeNode node : rete.getObjectTypeNodes() ) {
+            visit( node );
+        }
+    }
+
+    public void visitObjectTypeNode(final ObjectTypeNode node) {
+        System.out.println( indent() + node );
+
+        final FactHashTable memory = (FactHashTable) this.workingMemory.getNodeMemory( node );
+        checkObjectHashTable( memory );
+
+        this.indent++;
+        try {
+            final Field field = ObjectSource.class.getDeclaredField( "sink" );
+            field.setAccessible( true );
+            final ObjectSinkPropagator sink = (ObjectSinkPropagator) field.get( node );
+            final ObjectSink[] sinks = sink.getSinks();
+            for ( int i = 0, length = sinks.length; i < length; i++ ) {
+                visit( sinks[i] );
+            }
+        } catch ( final Exception e ) {
+            e.printStackTrace();
+        }
+        this.indent--;
+    }
+
+    public void visitAlphaNode(final AlphaNode node) {
+        System.out.println( indent() + node );
+
+        final FactHashTable memory = (FactHashTable) this.workingMemory.getNodeMemory( node );
+        checkObjectHashTable( memory );
+
+        this.indent++;
+        try {
+            final Field field = ObjectSource.class.getDeclaredField( "sink" );
+            field.setAccessible( true );
+            final ObjectSinkPropagator sink = (ObjectSinkPropagator) field.get( node );
+            final ObjectSink[] sinks = sink.getSinks();
+            for ( int i = 0, length = sinks.length; i < length; i++ ) {
+                visit( sinks[i] );
+            }
+        } catch ( final Exception e ) {
+            e.printStackTrace();
+        }
+        this.indent--;
+    }
+
+    public void visitLeftInputAdapterNode(final LeftInputAdapterNode node) {
+        System.out.println( indent() + node );
+
+        this.indent++;
+        try {
+            final Field field = TupleSource.class.getDeclaredField( "sink" );
+            field.setAccessible( true );
+            final TupleSinkPropagator sink = (TupleSinkPropagator) field.get( node );
+            final TupleSink[] sinks = sink.getSinks();
+            for ( int i = 0, length = sinks.length; i < length; i++ ) {
+                visit( sinks[i] );
+            }
+        } catch ( final Exception e ) {
+            e.printStackTrace();
+        }
+        this.indent--;
+    }
+
+    public void visitJoinNode(final JoinNode node) {
+        System.out.println( indent() + node );
+
+        try {
+            final BetaMemory memory = (BetaMemory) this.workingMemory.getNodeMemory( node );
+            checkObjectHashTable( memory.getFactHandleMemory() );
+            checkTupleMemory( memory.getTupleMemory() );
+        } catch ( final Exception e ) {
+            e.printStackTrace();
+        }
+
+        this.indent++;
+        try {
+            final Field field = TupleSource.class.getDeclaredField( "sink" );
+            field.setAccessible( true );
+            final TupleSinkPropagator sink = (TupleSinkPropagator) field.get( node );
+            final TupleSink[] sinks = sink.getSinks();
+            for ( int i = 0, length = sinks.length; i < length; i++ ) {
+                visit( sinks[i] );
+            }
+        } catch ( final Exception e ) {
+            e.printStackTrace();
+        }
+        this.indent--;
+    }
+
+    public void visitNotNode(final NotNode node) {
+        System.out.println( indent() + node );
+        try {
+            final BetaMemory memory = (BetaMemory) this.workingMemory.getNodeMemory( node );
+            checkObjectHashTable( memory.getFactHandleMemory() );
+            checkTupleMemory( memory.getTupleMemory() );
+        } catch ( final Exception e ) {
+            e.printStackTrace();
+        }
+
+        this.indent++;
+        try {
+            final Field field = TupleSource.class.getDeclaredField( "sink" );
+            field.setAccessible( true );
+            final TupleSinkPropagator sink = (TupleSinkPropagator) field.get( node );
+            final TupleSink[] sinks = sink.getSinks();
+            for ( int i = 0, length = sinks.length; i < length; i++ ) {
+                visit( sinks[i] );
+            }
+        } catch ( final Exception e ) {
+            e.printStackTrace();
+        }
+        this.indent--;
+    }
+
+    public void visitTerminalNode(final RuleTerminalNode node) {
+        System.out.println( indent() + node );
+        final TerminalNodeMemory memory = (TerminalNodeMemory) this.workingMemory.getNodeMemory( node );
+        checkTupleMemory( memory.getTupleMemory() );
+    }
+
+    //    private void checkObjectHashMap(final ObjectHashMap map) {
+    //        final Entry[] entries = map.getTable();
+    //        int count = 0;
+    //        for ( int i = 0, length = entries.length; i < length; i++ ) {
+    //            if ( entries[i] != null ) {
+    //                count++;
+    //            }
+    //        }
+    //
+    //        System.out.println( "ObjectHashMap: " + indent() + map.size() + ":" + count );
+    //        if ( map.size() != count ) {
+    //            System.out.println( indent() + "error" );
+    //        }
+    //    }
+
+    private void checkObjectHashTable(final FactHandleMemory memory) {
+        if ( memory instanceof FactHashTable ) {
+            checkFactHashTable( (FactHashTable) memory );
+        } else if ( memory instanceof FactHandleIndexHashTable ) {
+            checkFieldIndexHashTable( (FactHandleIndexHashTable) memory );
+        } else {
+            throw new RuntimeException( memory.getClass() + " should not be here" );
+        }
+    }
+
+    private void checkFactHashTable(final FactHashTable memory) {
+        final Entry[] entries = memory.getTable();
+        int count = 0;
+        for ( int i = 0, length = entries.length; i < length; i++ ) {
+            if ( entries[i] != null ) {
+                Entry entry = entries[i];
+                while ( entry != null ) {
+                    count++;
+                    entry = entry.getNext();
+                }
+            }
+        }
+
+        System.out.println( indent() + "FactHashTable: " + memory.size() + ":" + count );
+        if ( memory.size() != count ) {
+            System.out.println( indent() + "error" );
+        }
+    }
+
+    private void checkFieldIndexHashTable(final FactHandleIndexHashTable memory) {
+        final Entry[] entries = memory.getTable();
+        int factCount = 0;
+        int bucketCount = 0;
+        for ( int i = 0, length = entries.length; i < length; i++ ) {
+            if ( entries[i] != null ) {
+                FieldIndexEntry fieldIndexEntry = (FieldIndexEntry) entries[i];
+                while ( fieldIndexEntry != null ) {
+                    if ( fieldIndexEntry.getFirst() != null ) {
+                        Entry entry = fieldIndexEntry.getFirst();
+                        while ( entry != null ) {
+                            entry = entry.getNext();
+                            factCount++;
+                        }
+                    } else {
+                        System.out.println( "error : fieldIndexHashTable cannot have empty FieldIndexEntry objects" );
+                    }
+                    fieldIndexEntry = (FieldIndexEntry) fieldIndexEntry.getNext();
+                    bucketCount++;
+                }
+            }
+        }
+
+        try {
+            final Field field = AbstractHashTable.class.getDeclaredField( "size" );
+            field.setAccessible( true );
+            System.out.println( indent() + "FieldIndexBuckets: " + ((Integer) field.get( memory )).intValue() + ":" + bucketCount );
+            if ( ((Integer) field.get( memory )).intValue() != bucketCount ) {
+                System.out.println( indent() + "error" );
+            }
+        } catch ( final Exception e ) {
+            e.printStackTrace();
+        }
+
+        System.out.println( indent() + "FieldIndexFacts: " + memory.size() + ":" + factCount );
+        if ( memory.size() != factCount ) {
+            System.out.println( indent() + "error" );
+        }
+    }
+
+    private void checkTupleMemory(final TupleMemory memory) {
+        final Entry[] entries = memory.getTable();
+        int count = 0;
+        for ( int i = 0, length = entries.length; i < length; i++ ) {
+            if ( entries[i] != null ) {
+                Entry entry = entries[i];
+                while ( entry != null ) {
+                    count++;
+                    entry = entry.getNext();
+                }
+            }
+        }
+
+        System.out.println( indent() + "TupleMemory: " + memory.size() + ":" + count );
+        if ( memory.size() != count ) {
+            System.out.println( indent() + "error" );
+        }
+    }
+
+    private String indent() {
+        final StringBuffer buffer = new StringBuffer();
+        for ( int i = 0; i < this.indent; i++ ) {
+            buffer.append( "  " );
+        }
+        return buffer.toString();
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/NotNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/NotNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/NotNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,267 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.common.BetaConstraints;
+import org.drools.common.EmptyBetaConstraints;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.spi.PropagationContext;
+import org.drools.util.FactEntry;
+import org.drools.util.Iterator;
+
+/**
+ * <code>NotNode</code> extends <code>BetaNode</code> to perform tests for
+ * the non existence of a Fact plus one or more conditions. Where none existence
+ * is found the left ReteTuple is copied and propgated. Further to this it
+ * maintains the "truth" by cancelling any
+ * <code>Activation<code>s that are nolonger 
+ * considered true by the assertion of ReteTuple's or FactHandleImpl.  Tuples are considered to be asserted from the left input and facts from the right input.
+ * The <code>BetaNode</code> provides the BetaMemory to store assserted ReteTuples and <code>FactHandleImpl<code>s. Each fact handle is stored in the right 
+ * memory as a key in a <code>HashMap</code>, the value is an <code>ObjectMatches</code> instance which maintains a <code>LinkedList of <code>TuplesMatches - 
+ * The tuples that are matched with the handle. the left memory is a <code>LinkedList</code> of <code>ReteTuples</code> which maintains a <code>HashMa</code>, 
+ * where the keys are the matching <code>FactHandleImpl</code>s and the value is populated <code>TupleMatche</code>es, the keys are matched fact handles. 
+ * <code>TupleMatch</code> maintains a <code>List</code> of resulting joins, where there is joined <code>ReteTuple</code> per <code>TupleSink</code>.
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ *
+ */
+public class NotNode extends BetaNode {
+
+    private static final long serialVersionUID = 400L;
+    static int                notAssertObject  = 0;
+    static int                notAssertTuple   = 0;
+
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+
+    /**
+     * Construct.
+     * 
+     * @param leftInput
+     *            The left input <code>TupleSource</code>.
+     * @param rightInput
+     *            The right input <code>TupleSource</code>.
+     */
+    public NotNode(final int id,
+                   final TupleSource leftInput,
+                   final ObjectSource rightInput,
+                   final BetaConstraints joinNodeBinder,
+                   final BuildContext context) {
+        super( id,
+               leftInput,
+               rightInput,
+               joinNodeBinder );
+        this.tupleMemoryEnabled = context.isTupleMemoryEnabled();        
+    }
+
+    /**
+     * Assert a new <code>ReteTuple</code> from the left input. It iterates
+     * over the right <code>FactHandleImpl</code>'s if no matches are found
+     * the a copy of the <code>ReteTuple</code> is made and propagated.
+     * 
+     * @param tuple
+     *            The <code>Tuple</code> being asserted.
+     * @param context
+     *            The <code>PropagationContext</code>
+     * @param workingMemory
+     *            The working memory seesion.
+     */
+    public void assertTuple(final ReteTuple leftTuple,
+                            final PropagationContext context,
+                            final InternalWorkingMemory workingMemory) {
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+        
+        if ( this.tupleMemoryEnabled ) {
+            memory.getTupleMemory().add( leftTuple );
+        }
+
+        final Iterator it = memory.getFactHandleMemory().iterator( leftTuple );
+        this.constraints.updateFromTuple( workingMemory,
+                                          leftTuple );
+        
+        for ( FactEntry entry = (FactEntry) it.next(); entry != null; entry = (FactEntry) it.next() ) {
+            final InternalFactHandle handle = entry.getFactHandle();
+            if ( this.constraints.isAllowedCachedLeft( handle ) ) {
+                leftTuple.setMatch( handle );
+                break;
+            }
+        }
+        
+        this.constraints.resetTuple();
+
+        if ( leftTuple.getMatch() == null ) {
+            this.sink.propagateAssertTuple( leftTuple,
+                                            context,
+                                            workingMemory );
+        }
+    }
+
+    /**
+     * Assert a new <code>FactHandleImpl</code> from the right input. If it
+     * matches any left ReteTuple's that already has propagations then those
+     * propagations are retracted.
+     * 
+     * @param handle
+     *            The <code>FactHandleImpl</code> being asserted.
+     * @param context
+     *            The <code>PropagationContext</code>
+     * @param workingMemory
+     *            The working memory seesion.
+     */
+    public void assertObject(final InternalFactHandle handle,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+        memory.getFactHandleMemory().add( handle );
+        
+        if ( !this.tupleMemoryEnabled ) {
+            // do nothing here, as we know there are no left tuples at this stage in sequential mode.
+            return;
+        }        
+
+        final Iterator it = memory.getTupleMemory().iterator( handle );
+        this.constraints.updateFromFactHandle( workingMemory,
+                                               handle );
+        for ( ReteTuple tuple = (ReteTuple) it.next(); tuple != null; tuple = (ReteTuple) it.next() ) {
+            if ( this.constraints.isAllowedCachedRight( tuple ) &&  tuple.getMatch() == null) {
+                    tuple.setMatch( handle );
+                    this.sink.propagateRetractTuple( tuple,
+                                                     context,
+                                                     workingMemory );                    
+            }
+        }
+        
+        this.constraints.resetFactHandle();
+    }
+
+    /**
+     * Retract the <code>FactHandleImpl</code>. If the handle has any
+     * <code>ReteTuple</code> matches then those matches copied are propagated
+     * as new joins.
+     * 
+     * @param handle
+     *            the <codeFactHandleImpl</code> being retracted
+     * @param context
+     *            The <code>PropagationContext</code>
+     * @param workingMemory
+     *            The working memory seesion.
+     * @throws AssertionException
+     */
+    public void retractObject(final InternalFactHandle handle,
+                              final PropagationContext context,
+                              final InternalWorkingMemory workingMemory) {
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+        if ( !memory.getFactHandleMemory().remove( handle ) ) {
+            return;
+        }
+
+        final Iterator it = memory.getTupleMemory().iterator( handle );
+        this.constraints.updateFromFactHandle( workingMemory,
+                                               handle );
+        for ( ReteTuple tuple = (ReteTuple) it.next(); tuple != null; tuple = (ReteTuple) it.next() ) {
+            if ( this.constraints.isAllowedCachedRight( tuple ) ) {
+                
+                if ( tuple.getMatch() == handle ) {
+                    // reset the match                    
+                    tuple.setMatch( null );
+                    
+                    // find next match, remember it and break.
+                    final Iterator tupleIt = memory.getFactHandleMemory().iterator( tuple );
+                    this.constraints.updateFromTuple( workingMemory, tuple );
+                    
+                    for ( FactEntry entry = (FactEntry) tupleIt.next(); entry != null; entry = (FactEntry) tupleIt.next() ) {
+                        final InternalFactHandle rightHandle = entry.getFactHandle();
+                        if ( this.constraints.isAllowedCachedLeft( rightHandle ) ) {
+                            tuple.setMatch( rightHandle );
+                            break;
+                        }
+                    }
+                    
+                    this.constraints.resetTuple();
+                    // if there is now no new tuple match then propagate assert.
+                    if ( tuple.getMatch() == null ) {
+                        this.sink.propagateAssertTuple( tuple,
+                                                        context,
+                                                        workingMemory );
+                    }                    
+                }
+            }
+        }
+        
+        this.constraints.resetFactHandle();
+    }
+
+    /**
+     * Retract the
+     * <code>ReteTuple<code>, any resulting proppagated joins are also retracted. 
+     * 
+     * @param key
+     *            The tuple key.
+     * @param context
+     *            The <code>PropagationContext</code>
+     * @param workingMemory
+     *            The working memory seesion.
+     */
+    public void retractTuple(final ReteTuple leftTuple,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+
+        // Must use the tuple in memory as it has the tuple matches count
+        final ReteTuple tuple = memory.getTupleMemory().remove( leftTuple );
+        if ( tuple == null ) {
+            return;
+        }
+
+        if ( tuple.getMatch() ==  null) {
+            this.sink.propagateRetractTuple( tuple,
+                                             context,
+                                             workingMemory );
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.BaseNode#updateNewNode(org.drools.reteoo.WorkingMemoryImpl, org.drools.spi.PropagationContext)
+     */
+    public void updateSink(final TupleSink sink,
+                           final PropagationContext context,
+                           final InternalWorkingMemory workingMemory) {
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+
+        final Iterator tupleIter = memory.getTupleMemory().iterator();
+        for ( ReteTuple tuple = (ReteTuple) tupleIter.next(); tuple != null; tuple = (ReteTuple) tupleIter.next() ) {
+            if ( tuple.getMatch() == null ) {
+                sink.assertTuple( new ReteTuple( tuple ),
+                                  context,
+                                  workingMemory );
+            }
+        }
+    }
+
+    public String toString() {
+        ObjectSource source = this.rightInput;
+        while ( !(source instanceof ObjectTypeNode) ) {
+            source = source.objectSource;
+        }
+
+        return "[NotNode - " + ((ObjectTypeNode) source).getObjectType() + "]";
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectSink.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectSink.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectSink.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,68 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+
+/**
+ * Receiver of propagated <code>FactHandleImpl</code>s from a
+ * <code>ObjectSource</code>.
+ * 
+ * @see ObectSource
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ *
+ */
+public interface ObjectSink
+    extends
+    Sink {
+
+    /**
+     * Assert a new <code>FactHandleImpl</code>.
+     * 
+     * @param handle
+     *            The asserted <code>FactHandle/code>.
+     * @param context
+     *             The <code>PropagationContext</code> of the <code>WorkingMemory<code> action.           
+     * @param workingMemory
+     *            the <code>WorkingMemory</code> session.
+     */
+    void assertObject(InternalFactHandle handle,
+                      PropagationContext context,
+                      InternalWorkingMemory workingMemory);
+
+    /**
+     * Retract an existing <code>FactHandleImpl</code>.
+     * 
+     * @param handle
+     *            The <code>FactHandle/code> to retract.
+     * @param context
+     *             The <code>PropagationContext</code> of the <code>WorkingMemory<code> action.           
+     * @param workingMemory
+     *            the <code>WorkingMemory</code> session.
+     */
+    void retractObject(InternalFactHandle handle,
+                       PropagationContext context,
+                       InternalWorkingMemory workingMemory);
+
+    public boolean isObjectMemoryEnabled();
+
+    public void setObjectMemoryEnabled(boolean objectMemoryOn);
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectSinkNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectSinkNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectSinkNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,59 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Items placed in a <code>LinkedList<code> must implement this interface .
+ * 
+ * @see TupleSinkNodeList
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ */
+public interface ObjectSinkNode
+    extends
+    ObjectSink {
+
+    /**
+     * Returns the next node
+     * @return
+     *      The next LinkedListNode
+     */
+    public ObjectSinkNode getNextObjectSinkNode();
+
+    /**
+     * Sets the next node 
+     * @param next
+     *      The next LinkedListNode
+     */
+    public void setNextObjectSinkNode(ObjectSinkNode next);
+
+    /**
+     * Returns the previous node
+     * @return
+     *      The previous LinkedListNode
+     */
+    public ObjectSinkNode getPreviousObjectSinkNode();
+
+    /**
+     * Sets the previous node 
+     * @param previous
+     *      The previous LinkedListNode
+     */
+    public void setPreviousObjectSinkNode(ObjectSinkNode previous);
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectSinkNodeList.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectSinkNodeList.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectSinkNodeList.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,229 @@
+package org.drools.reteoo;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * This is a simple linked linked implementation. Each node must implement </code>LinkedListNode<code> so that it references
+ * the node before and after it. This way a node can be removed without having to scan the list to find it. This class
+ * does not provide an Iterator implementation as its designed for efficiency and not genericity. There are a number of 
+ * ways to iterate the list.
+ * <p>
+ * Simple iterator:
+ * <pre>
+ * for ( LinkedListNode node = list.getFirst(); node != null; node =  node.getNext() ) {
+ * }
+ * </pre>
+ * 
+ * Iterator that pops the first entry:
+ * <pre>
+ * for ( LinkedListNode node = list.removeFirst(); node != null; node = list.removeFirst() ) {
+ * }
+ * </pre>
+ *
+ *
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ *
+ */
+public class ObjectSinkNodeList
+    implements
+    Serializable {
+    private static final long serialVersionUID = 400L;
+
+    private ObjectSinkNode    firstNode;
+    private ObjectSinkNode    lastNode;
+
+    private int               size;
+
+    /**
+     * Construct an empty <code>LinkedList</code>
+     */
+    public ObjectSinkNodeList() {
+
+    }
+
+    /**
+     * Add a <code>ObjectSinkNode</code> to the list. If the <code>LinkedList</code> is empty then the first and 
+     * last nodes are set to the added node.
+     * 
+     * @param node
+     *      The <code>ObjectSinkNode</code> to be added
+     */
+    public void add(final ObjectSinkNode node) {
+        if ( this.firstNode == null ) {
+            this.firstNode = node;
+            this.lastNode = node;;
+        } else {
+            this.lastNode.setNextObjectSinkNode( node );
+            node.setPreviousObjectSinkNode( this.lastNode );
+            this.lastNode = node;
+        }
+        this.size++;
+    }
+
+    /**
+     * Removes a <code>ObjectSinkNode</code> from the list. This works by attach the previous reference to the child reference.
+     * When the node to be removed is the first node it calls <code>removeFirst()</code>. When the node to be removed is the last node
+     * it calls <code>removeLast()</code>.
+     * 
+     * @param node
+     *      The <code>ObjectSinkNode</code> to be removed.
+     */
+    public void remove(final ObjectSinkNode node) {
+        if ( (this.firstNode != node) && (this.lastNode != node) ) {
+            node.getPreviousObjectSinkNode().setNextObjectSinkNode( node.getNextObjectSinkNode() );
+            node.getNextObjectSinkNode().setPreviousObjectSinkNode( node.getPreviousObjectSinkNode() );
+            this.size--;
+            node.setPreviousObjectSinkNode( null );
+            node.setNextObjectSinkNode( null );
+
+        } else {
+            if ( this.firstNode == node ) {
+                removeFirst();
+            } else if ( this.lastNode == node ) {
+                removeLast();
+            }
+        }
+    }
+
+    /**
+     * Return the first node in the list
+     * @return
+     *      The first <code>ObjectSinkNode</code>.
+     */
+    public final ObjectSinkNode getFirst() {
+        return this.firstNode;
+    }
+
+    /**
+     * Return the last node in the list
+     * @return
+     *      The last <code>ObjectSinkNode</code>.
+     */
+    public final ObjectSinkNode getLast() {
+        return this.lastNode;
+    }
+
+    /**
+     * Remove the first node from the list. The next node then becomes the first node. If this is the last 
+     * node then both first and last node references are set to null.
+     * 
+     * @return
+     *      The first <code>ObjectSinkNode</code>.
+     */
+    public ObjectSinkNode removeFirst() {
+        if ( this.firstNode == null ) {
+            return null;
+        }
+        final ObjectSinkNode node = this.firstNode;
+        this.firstNode = node.getNextObjectSinkNode();
+        node.setNextObjectSinkNode( null );
+        if ( this.firstNode != null ) {
+            this.firstNode.setPreviousObjectSinkNode( null );
+        } else {
+            this.lastNode = null;
+        }
+        this.size--;
+        return node;
+    }
+
+    /**
+     * Remove the last node from the list. The previous node then becomes the last node. If this is the last 
+     * node then both first and last node references are set to null.
+     * 
+     * @return
+     *      The first <code>ObjectSinkNode</code>.
+     */
+    public ObjectSinkNode removeLast() {
+        if ( this.lastNode == null ) {
+            return null;
+        }
+        final ObjectSinkNode node = this.lastNode;
+        this.lastNode = node.getPreviousObjectSinkNode();
+        node.setPreviousObjectSinkNode( null );
+        if ( this.lastNode != null ) {
+            this.lastNode.setNextObjectSinkNode( null );
+        } else {
+            this.firstNode = this.lastNode;
+        }
+        this.size--;
+        return node;
+    }
+
+    /**
+     * @return
+     *      boolean value indicating the empty status of the list
+     */
+    public final boolean isEmpty() {
+        return (this.firstNode == null);
+    }
+
+    /**
+     * Iterates the list removing all the nodes until there are no more nodes to remove. 
+     */
+    public void clear() {
+        while ( removeFirst() != null ) {
+        }
+    }
+
+    /**
+     * @return
+     *     return size of the list as an int
+     */
+    public final int size() {
+        return this.size;
+    }
+
+    /**
+     * Returns a list iterator
+     * @return
+     */
+    public Iterator iterator() {
+        return new Iterator() {
+            private ObjectSinkNode currentNode = null;
+            private ObjectSinkNode nextNode    = getFirst();
+
+            public boolean hasNext() {
+                return (this.nextNode != null);
+            }
+
+            public Object next() {
+                this.currentNode = this.nextNode;
+                if ( this.currentNode != null ) {
+                    this.nextNode = this.currentNode.getNextObjectSinkNode();
+                } else {
+                    throw new NoSuchElementException( "No more elements to return" );
+                }
+                return this.currentNode;
+            }
+
+            public void remove() {
+                if ( this.currentNode != null ) {
+                    ObjectSinkNodeList.this.remove( this.currentNode );
+                    this.currentNode = null;
+                } else {
+                    throw new IllegalStateException( "No item to remove. Call next() before calling remove()." );
+                }
+            }
+        };
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectSinkPropagator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectSinkPropagator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectSinkPropagator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,24 @@
+package org.drools.reteoo;
+
+import java.io.Serializable;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+
+public interface ObjectSinkPropagator
+    extends
+    Serializable {
+    public void propagateAssertObject(InternalFactHandle handle,
+                                      PropagationContext context,
+                                      InternalWorkingMemory workingMemory);
+
+    public void propagateRetractObject(InternalFactHandle handle,
+                                       PropagationContext context,
+                                       InternalWorkingMemory workingMemory,
+                                       boolean useHash);
+
+    public ObjectSink[] getSinks();
+    
+    public int size();
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectSource.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectSource.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectSource.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,137 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.drools.common.BaseNode;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+
+/**
+ * A source of <code>FactHandle</code>s for an <code>ObjectSink</code>.
+ * 
+ * <p>
+ * Nodes that propagate <code>FactHandleImpl</code> extend this class.
+ * </p>
+ * 
+ * @see ObjectSource
+ * @see DefaultFactHandle
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ */
+public abstract class ObjectSource extends BaseNode
+    implements
+    Serializable {
+    // ------------------------------------------------------------
+    // Instance members
+    // ------------------------------------------------------------
+
+    /** The destination for <code>FactHandleImpl</code>. */
+    protected ObjectSinkPropagator sink;
+
+    protected ObjectSource         objectSource;
+
+    private int                    alphaNodeHashingThreshold;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    /**
+     * Single parameter constructor that specifies the unique id of the node.
+     * 
+     * @param id
+     */
+    ObjectSource(final int id) {
+        this( id,
+              null,
+              3 );
+    }
+
+    /**
+     * Single parameter constructor that specifies the unique id of the node.
+     * 
+     * @param id
+     */
+    ObjectSource(final int id,
+                 final ObjectSource objectSource,
+                 final int alphaNodeHashingThreshold) {
+        super( id );
+        this.objectSource = objectSource;
+        this.alphaNodeHashingThreshold = alphaNodeHashingThreshold;
+        this.sink = EmptyObjectSinkAdapter.getInstance();
+    }
+
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+
+    /**
+     * Adds the <code>ObjectSink</code> so that it may receive
+     * <code>FactHandleImpl</code> propagated from this
+     * <code>ObjectSource</code>.
+     * 
+     * @param objectSink
+     *            The <code>ObjectSink</code> to receive propagated
+     *            <code>FactHandleImpl</code>.
+     */
+    protected void addObjectSink(final ObjectSink objectSink) {
+        if ( this.sink == EmptyObjectSinkAdapter.getInstance() ) {
+            this.sink = new SingleObjectSinkAdapter( objectSink );
+        } else if ( this.sink instanceof SingleObjectSinkAdapter ) {
+            final CompositeObjectSinkAdapter sinkAdapter = new CompositeObjectSinkAdapter( this.alphaNodeHashingThreshold );
+            sinkAdapter.addObjectSink( this.sink.getSinks()[0] );
+            sinkAdapter.addObjectSink( objectSink );
+            this.sink = sinkAdapter;
+        } else {
+            ((CompositeObjectSinkAdapter) this.sink).addObjectSink( objectSink );
+        }
+    }
+
+    /**
+     * Removes the <code>ObjectSink</code>
+     * 
+     * @param objectSink
+     *            The <code>ObjectSink</code> to remove
+     */
+    protected void removeObjectSink(final ObjectSink objectSink) {
+        if ( this.sink == EmptyObjectSinkAdapter.getInstance() ) {
+            throw new IllegalArgumentException( "Cannot remove a sink, when the list of sinks is null" );
+        }
+
+        if ( this.sink instanceof SingleObjectSinkAdapter ) {
+            this.sink = EmptyObjectSinkAdapter.getInstance();
+        } else {
+            final CompositeObjectSinkAdapter sinkAdapter = (CompositeObjectSinkAdapter) this.sink;
+            sinkAdapter.removeObjectSink( objectSink );
+            if ( sinkAdapter.size() == 1 ) {
+                this.sink = new SingleObjectSinkAdapter( sinkAdapter.getSinks()[0] );
+            }
+        }
+    }
+
+    public abstract void updateSink(ObjectSink sink,
+                                    PropagationContext context,
+                                    InternalWorkingMemory workingMemory);
+
+    public ObjectSinkPropagator getSinkPropagator() {
+        return this.sink;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectTypeConf.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectTypeConf.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectTypeConf.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Nov 26, 2007
+ */
+package org.drools.reteoo;
+
+import org.drools.RuntimeDroolsException;
+
+public interface ObjectTypeConf {
+    public ObjectTypeNode[] getObjectTypeNodes();
+
+    public boolean isShadowEnabled();
+
+    public Object getShadow(final Object fact) throws RuntimeDroolsException;
+
+    public ObjectTypeNode getConcreteObjectTypeNode();
+
+    public void resetCache();
+
+    public boolean isAssignableFrom(Object object);
+    
+    public boolean isActive();
+    
+    public boolean isEvent();
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectTypeNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectTypeNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ObjectTypeNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,352 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.drools.RuleBaseConfiguration;
+import org.drools.common.BaseNode;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.NodeMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.Declaration;
+import org.drools.rule.EntryPoint;
+import org.drools.spi.Constraint;
+import org.drools.spi.ObjectType;
+import org.drools.spi.PropagationContext;
+import org.drools.util.FactEntry;
+import org.drools.util.FactHashTable;
+import org.drools.util.Iterator;
+
+/**
+ * <code>ObjectTypeNodes<code> are responsible for filtering and propagating the matching
+ * fact assertions propagated from the <code>Rete</code> node using <code>ObjectType</code> interface.
+ * <p>
+ * The assert and retract methods do not attempt to filter as this is the role of the <code>Rete</code>
+ * node which builds up a cache of matching <code>ObjectTypdeNodes</code>s for each asserted object, using
+ * the <code>matches(Object object)</code> method. Incorrect propagation in these methods is not checked and
+ * will result in <code>ClassCastExpcections</code> later on in the network.
+ * <p>
+ * Filters <code>Objects</code> coming from the <code>Rete</code> using a
+ * <code>ObjectType</code> semantic module.
+ * 
+ * 
+ * @see ObjectType
+ * @see Rete
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ */
+public class ObjectTypeNode extends ObjectSource
+    implements
+    ObjectSink,
+    Serializable,
+    NodeMemory
+
+{
+    // ------------------------------------------------------------
+    // Instance members
+    // ------------------------------------------------------------
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    /** The <code>ObjectType</code> semantic module. */
+    private final ObjectType  objectType;
+
+    private boolean           skipOnModify     = false;
+
+    private boolean           objectMemoryEnabled;
+
+    /**
+     * Construct given a semantic <code>ObjectType</code> and the provided
+     * unique id. All <code>ObjectTypdeNode</code> have node memory.
+     * 
+     * @param id
+     *          The unique id for the node.
+     * @param objectType
+     *           The semantic object-type differentiator.
+     */
+    public ObjectTypeNode(final int id,
+                          final EntryPointNode source,
+                          final ObjectType objectType,
+                          final BuildContext context) {
+        super( id,
+               source,
+               context.getRuleBase().getConfiguration().getAlphaNodeHashingThreshold() );
+        this.objectType = objectType;
+        setObjectMemoryEnabled( context.isObjectTypeNodeMemoryEnabled() );
+    }
+
+    /**
+     * Retrieve the semantic <code>ObjectType</code> differentiator.
+     * 
+     * @return 
+     *      The semantic <code>ObjectType</code> differentiator.
+     */
+    public ObjectType getObjectType() {
+        return this.objectType;
+    }
+
+    /**
+     * Tests the provided object to see if this <code>ObjectTypeNode</code> can receive the object
+     * for assertion and retraction propagations.
+     * 
+     * @param object
+     * @return
+     *      boolean value indicating whether the <code>ObjectTypeNode</code> can receive the object.
+     */
+    public boolean matches(final Object object) {
+        return this.objectType.matches( object );
+    }
+
+    public boolean isAssignableFrom(final Object object) {
+        return this.objectType.isAssignableFrom( object );
+    }
+
+    /**
+     * Propagate the <code>FactHandleimpl</code> through the <code>Rete</code> network. All
+     * <code>FactHandleImpl</code> should be remembered in the node memory, so that later runtime rule attachmnents
+     * can have the matched facts propagated to them.
+     * 
+     * @param handle
+     *            The fact handle.
+     * @param object
+     *            The object to assert.
+     * @param workingMemory
+     *            The working memory session.
+     */
+    public void assertObject(final InternalFactHandle handle,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+        if ( context.getType() == PropagationContext.MODIFICATION && this.skipOnModify && context.getDormantActivations() == 0 ) {
+            // we do this after the shadowproxy update, just so that its up to date for the future
+            return;
+        }
+
+        if ( this.objectMemoryEnabled ) {
+            final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( this );
+            memory.add( handle,
+                        false );
+        }
+
+        this.sink.propagateAssertObject( handle,
+                                         context,
+                                         workingMemory );
+    }
+
+    /**
+     * Retract the <code>FactHandleimpl</code> from the <code>Rete</code> network. Also remove the 
+     * <code>FactHandleImpl</code> from the node memory.
+     * 
+     * @param handle
+     *            The fact handle.
+     * @param object
+     *            The object to assert.
+     * @param workingMemory
+     *            The working memory session.
+     */
+    public void retractObject(final InternalFactHandle handle,
+                              final PropagationContext context,
+                              final InternalWorkingMemory workingMemory) {
+
+        if ( context.getType() == PropagationContext.MODIFICATION && this.skipOnModify && context.getDormantActivations() == 0 ) {
+            return;
+        }
+
+        final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( this );
+        memory.remove( handle );
+
+        this.sink.propagateRetractObject( handle,
+                                          context,
+                                          workingMemory,
+                                          true );
+    }
+
+    public void updateSink(final ObjectSink sink,
+                           final PropagationContext context,
+                           final InternalWorkingMemory workingMemory) {
+        final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( this );
+        final Iterator it = memory.iterator();
+        for ( FactEntry entry = (FactEntry) it.next(); entry != null; entry = (FactEntry) it.next() ) {
+            sink.assertObject( entry.getFactHandle(),
+                               context,
+                               workingMemory );
+        }
+    }
+
+    /**
+     * Rete needs to know that this ObjectTypeNode has been added
+     */
+    public void attach() {
+        this.objectSource.addObjectSink( this );
+    }
+
+    public void attach(final InternalWorkingMemory[] workingMemories) {
+        attach();
+
+        // we need to call updateSink on Rete, because someone 
+        // might have already added facts matching this ObjectTypeNode 
+        // to working memories
+        for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+            final InternalWorkingMemory workingMemory = workingMemories[i];
+            final PropagationContextImpl propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
+                                                                                          PropagationContext.RULE_ADDITION,
+                                                                                          null,
+                                                                                          null );
+            propagationContext.setEntryPoint( ((EntryPointNode) this.objectSource).getEntryPoint() );
+            this.objectSource.updateSink( this,
+                                          propagationContext,
+                                          workingMemory );
+        }
+    }
+
+    public void remove(ReteooBuilder builder,
+                       final BaseNode node, final InternalWorkingMemory[] workingMemories) {
+        if ( !node.isInUse() ) {
+            removeObjectSink( (ObjectSink) node );
+        }
+        removeShare(builder);
+        if ( !this.isInUse() ) {
+            for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+                workingMemories[i].clearNodeMemory( this );
+            }
+            this.objectSource.removeObjectSink( this );
+        }
+    }
+
+    /**
+     * Rete needs to know that this ObjectTypeNode has had new nodes attached to
+     * it one one of its ancestors
+     */
+    public void addShare() {
+        super.addShare();
+    }
+
+    /**
+     * Creates memory for the node using PrimitiveLongMap as its optimised for storage and reteivals of Longs.
+     * However PrimitiveLongMap is not ideal for spase data. So it should be monitored incase its more optimal
+     * to switch back to a standard HashMap.
+     */
+    public Object createMemory(final RuleBaseConfiguration config) {
+        return new FactHashTable();
+    }
+
+    public boolean isObjectMemoryEnabled() {
+        return this.objectMemoryEnabled;
+    }
+
+    public void setObjectMemoryEnabled(boolean objectMemoryEnabled) {
+        this.objectMemoryEnabled = objectMemoryEnabled;
+    }
+
+    public String toString() {
+        return "[ObjectTypeNode(" + this.id + ")::" + ((EntryPointNode)this.objectSource).getEntryPoint() + " objectType=" + this.objectType + "]";
+    }
+
+    /**
+     * Uses he hashCode() of the underlying ObjectType implementation.
+     */
+    public int hashCode() {
+        return this.objectType.hashCode() ^ this.objectSource.hashCode();
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof ObjectTypeNode) ) {
+            return false;
+        }
+
+        final ObjectTypeNode other = (ObjectTypeNode) object;
+
+        return this.objectType.equals( other.objectType ) && this.objectSource.equals( other.objectSource );
+    }
+
+    /** 
+     * @inheritDoc
+     */
+    protected void addObjectSink(final ObjectSink objectSink) {
+        super.addObjectSink( objectSink );
+        this.skipOnModify = canSkipOnModify( this.sink.getSinks() );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    protected void removeObjectSink(final ObjectSink objectSink) {
+        super.removeObjectSink( objectSink );
+        this.skipOnModify = canSkipOnModify( this.sink.getSinks() );
+    }
+
+    /**
+     * Checks if a modify action on this object type may
+     * be skipped because no constraint is applied to it
+     *  
+     * @param sinks
+     * @return
+     */
+    private boolean canSkipOnModify(final Sink[] sinks) {
+        // If we have no alpha or beta node with constraints on this ObjectType, we can just skip modifies
+        boolean hasConstraints = false;
+        for ( int i = 0; i < sinks.length && !hasConstraints; i++ ) {
+            if ( sinks[i] instanceof AlphaNode ) {
+                hasConstraints = this.usesDeclaration( ((AlphaNode) sinks[i]).getConstraint() );
+            } else if ( sinks[i] instanceof BetaNode && ((BetaNode) sinks[i]).getConstraints().length > 0 ) {
+                hasConstraints = this.usesDeclaration( ((BetaNode) sinks[i]).getConstraints() );
+            }
+            if ( !hasConstraints && sinks[i] instanceof ObjectSource ) {
+                hasConstraints = this.canSkipOnModify( ((ObjectSource) sinks[i]).getSinkPropagator().getSinks() );
+            } else if ( sinks[i] instanceof TupleSource ) {
+                hasConstraints = this.canSkipOnModify( ((TupleSource) sinks[i]).getSinkPropagator().getSinks() );
+            }
+        }
+
+        // Can only skip if we have no constraints
+        return !hasConstraints;
+    }
+
+    private boolean usesDeclaration(final Constraint[] constraints) {
+        boolean usesDecl = false;
+        for ( int i = 0; !usesDecl && i < constraints.length; i++ ) {
+            usesDecl = this.usesDeclaration( constraints[i] );
+        }
+        return usesDecl;
+    }
+
+    private boolean usesDeclaration(final Constraint constraint) {
+        boolean usesDecl = false;
+        final Declaration[] declarations = constraint.getRequiredDeclarations();
+        for ( int j = 0; !usesDecl && j < declarations.length; j++ ) {
+            usesDecl = (declarations[j].getPattern().getObjectType() == this.objectType);
+        }
+        return usesDecl;
+    }
+
+    /**
+     * @return the entryPoint
+     */
+    public EntryPoint getEntryPoint() {
+        return ((EntryPointNode)this.objectSource).getEntryPoint();
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/PropagationQueuingNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/PropagationQueuingNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/PropagationQueuingNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,357 @@
+/*
+ * Copyright 2008 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;
+
+import java.io.Serializable;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuntimeDroolsException;
+import org.drools.common.BaseNode;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.NodeMemory;
+import org.drools.common.WorkingMemoryAction;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.spi.PropagationContext;
+
+/**
+ * A node that will add the propagation to the working memory actions queue,
+ * in order to allow multiple threads to concurrently assert objects to multiple
+ * entry points.
+ * 
+ * @author etirelli
+ *
+ */
+public class PropagationQueuingNode extends ObjectSource
+    implements
+    ObjectSinkNode,
+    NodeMemory {
+
+    private static final long serialVersionUID = -615639068150958767L;
+    
+    // should we make this one configurable?
+    private static final int PROPAGATION_SLICE_LIMIT = 1000;
+
+    private ObjectSinkNode    previousObjectSinkNode;
+    private ObjectSinkNode    nextObjectSinkNode;
+    private PropagateAction   action;
+
+    /**
+     * Construct a <code>PropagationQueuingNode</code> that will queue up
+     * propagations until it the engine reaches a safe propagation point,
+     * when all the queued facts are propagated.
+     * 
+     * @param id Node's ID
+     * @param constraint Node's constraints
+     * @param objectSource Node's object source
+     * @param hasMemory true if node shall be configured with local memory. False otherwise.
+     */
+    public PropagationQueuingNode(final int id,
+                                  final ObjectSource objectSource,
+                                  final BuildContext context) {
+        super( id,
+               objectSource,
+               context.getRuleBase().getConfiguration().getAlphaNodeHashingThreshold() );
+        this.action = new PropagateAction( this );
+    }
+
+    /**
+     * @see org.drools.reteoo.ObjectSource#updateSink(org.drools.reteoo.ObjectSink, org.drools.spi.PropagationContext, org.drools.common.InternalWorkingMemory)
+     */
+    @Override
+    public void updateSink(ObjectSink sink,
+                           PropagationContext context,
+                           InternalWorkingMemory workingMemory) {
+
+        final PropagationQueueingNodeMemory memory = (PropagationQueueingNodeMemory) workingMemory.getNodeMemory( this );
+
+        // this is just sanity code. We may remove it in the future, but keeping it for now.
+        if ( !memory.isEmpty() ) {
+            throw new RuntimeDroolsException( "Error updating sink. Not safe to update sink as the PropagatingQueueingNode memory is not for node: " + this.toString() );
+        }
+
+        // as this node is simply a queue, ask object source to update the child sink directly
+        this.objectSource.updateSink( sink,
+                                      context,
+                                      workingMemory );
+    }
+
+    /**
+     * @see org.drools.common.BaseNode#attach()
+     */
+    @Override
+    public void attach() {
+        this.objectSource.addObjectSink( this );
+    }
+
+    /**
+     * @see org.drools.common.BaseNode#attach(org.drools.common.InternalWorkingMemory[])
+     */
+    @Override
+    public void attach(InternalWorkingMemory[] workingMemories) {
+        attach();
+        // this node does not require update, so nothing else to do.
+    }
+
+    /**
+     * @see org.drools.common.BaseNode#remove(ReteooBuilder, org.drools.common.BaseNode, org.drools.common.InternalWorkingMemory[])
+     */
+    @Override
+    public void remove(ReteooBuilder builder,
+                       BaseNode node, InternalWorkingMemory[] workingMemories) {
+        if ( !node.isInUse() ) {
+            removeObjectSink( (ObjectSink) node );
+        }
+        removeShare(builder);
+        if ( !this.isInUse() ) {
+            for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+                workingMemories[i].clearNodeMemory( this );
+            }
+        }
+        this.objectSource.remove( builder,
+                                  this, workingMemories );
+    }
+
+    /**
+     * @see org.drools.reteoo.ObjectSinkNode#getNextObjectSinkNode()
+     */
+    public ObjectSinkNode getNextObjectSinkNode() {
+        return this.nextObjectSinkNode;
+    }
+
+    /**
+     * @see org.drools.reteoo.ObjectSinkNode#getPreviousObjectSinkNode()
+     */
+    public ObjectSinkNode getPreviousObjectSinkNode() {
+        return this.previousObjectSinkNode;
+    }
+
+    /**
+     * @see org.drools.reteoo.ObjectSinkNode#setNextObjectSinkNode(org.drools.reteoo.ObjectSinkNode)
+     */
+    public void setNextObjectSinkNode(ObjectSinkNode next) {
+        this.nextObjectSinkNode = next;
+    }
+
+    /**
+     * @see org.drools.reteoo.ObjectSinkNode#setPreviousObjectSinkNode(org.drools.reteoo.ObjectSinkNode)
+     */
+    public void setPreviousObjectSinkNode(ObjectSinkNode previous) {
+        this.previousObjectSinkNode = previous;
+    }
+
+    /**
+     * @see org.drools.reteoo.ObjectSink#assertObject(org.drools.common.InternalFactHandle, org.drools.spi.PropagationContext, org.drools.common.InternalWorkingMemory)
+     */
+    public void assertObject(InternalFactHandle handle,
+                             PropagationContext context,
+                             InternalWorkingMemory workingMemory) {
+        final PropagationQueueingNodeMemory memory = (PropagationQueueingNodeMemory) workingMemory.getNodeMemory( this );
+        memory.addAction( new AssertAction( handle,
+                                            context ) );
+
+        // if not queued yet, we need to queue it up
+        if ( memory.isQueued().compareAndSet( false,
+                                              true ) ) {
+            workingMemory.queueWorkingMemoryAction( this.action );
+        }
+    }
+
+    /**
+     * @see org.drools.reteoo.ObjectSink#isObjectMemoryEnabled()
+     */
+    public boolean isObjectMemoryEnabled() {
+        return true;
+    }
+
+    /**
+     * @see org.drools.reteoo.ObjectSink#retractObject(org.drools.common.InternalFactHandle, org.drools.spi.PropagationContext, org.drools.common.InternalWorkingMemory)
+     */
+    public void retractObject(InternalFactHandle handle,
+                              PropagationContext context,
+                              InternalWorkingMemory workingMemory) {
+        final PropagationQueueingNodeMemory memory = (PropagationQueueingNodeMemory) workingMemory.getNodeMemory( this );
+        memory.addAction( new RetractAction( handle,
+                                             context ) );
+
+        // if not queued yet, we need to queue it up
+        if ( memory.isQueued().compareAndSet( false,
+                                              true ) ) {
+            workingMemory.queueWorkingMemoryAction( this.action );
+        }
+    }
+
+    /**
+     * Propagate all queued actions (asserts and retracts).
+     * 
+     * This method implementation is based on optimistic behavior to avoid the 
+     * use of locks. There may eventually be a minimum wasted effort, but overall
+     * it will be better than paying for the lock's cost.
+     * 
+     * @param workingMemory
+     */
+    public void propagateActions(InternalWorkingMemory workingMemory) {
+        final PropagationQueueingNodeMemory memory = (PropagationQueueingNodeMemory) workingMemory.getNodeMemory( this );
+
+        // first we clear up the action queued flag
+        memory.isQueued().set( false );
+
+        // we limit the propagation to avoid a hang when this queue is never empty
+        Action next = memory.getNext();
+        for( int counter = 0; next != null && counter < PROPAGATION_SLICE_LIMIT; next = memory.getNext(), counter++ ) {
+            next.execute( this.sink, workingMemory );
+        }
+        
+        if( memory.hasNext() ) {
+            // add action to the queue again.
+            memory.isQueued().set( true );
+            workingMemory.queueWorkingMemoryAction( this.action );
+        }
+    }
+
+    /**
+     * @see org.drools.reteoo.ObjectSink#setObjectMemoryEnabled(boolean)
+     */
+    public void setObjectMemoryEnabled(boolean objectMemoryOn) {
+        throw new UnsupportedOperationException( "PropagationQueueingNode must have its node memory enabled." );
+    }
+
+    public Object createMemory(RuleBaseConfiguration config) {
+        return new PropagationQueueingNodeMemory();
+    }
+
+    /**
+     * Memory implementation for the node
+     * 
+     * @author etirelli
+     */
+    private static class PropagationQueueingNodeMemory
+        implements
+        Serializable {
+
+        private static final long             serialVersionUID = 7372028632974484023L;
+
+        private ConcurrentLinkedQueue<Action> queue;
+
+        // "singleton" action - there is one of this for each node in each working memory
+        private AtomicBoolean                 isQueued;
+
+        public PropagationQueueingNodeMemory() {
+            super();
+            this.queue = new ConcurrentLinkedQueue<Action>();
+            this.isQueued = new AtomicBoolean( false );
+        }
+
+        public boolean isEmpty() {
+            return this.queue.isEmpty();
+        }
+
+        public void addAction(Action action) {
+            this.queue.add( action );
+        }
+
+        public Action getNext() {
+            return this.queue.poll();
+        }
+
+        public boolean hasNext() {
+            return this.queue.peek() != null;
+        }
+
+        public AtomicBoolean isQueued() {
+            return isQueued;
+        }
+    }
+
+    private static abstract class Action
+        implements
+        Serializable {
+
+        protected final InternalFactHandle handle;
+        protected final PropagationContext context;
+
+        public Action(InternalFactHandle handle,
+                      PropagationContext context) {
+            super();
+            this.handle = handle;
+            this.context = context;
+        }
+
+        public abstract void execute(final ObjectSinkPropagator sink,
+                                     final InternalWorkingMemory workingMemory);
+    }
+
+    private static class AssertAction extends Action {
+        private static final long serialVersionUID = -8478488926430845209L;
+
+        public AssertAction(final InternalFactHandle handle,
+                            final PropagationContext context) {
+            super( handle,
+                   context );
+        }
+
+        public void execute(final ObjectSinkPropagator sink,
+                            final InternalWorkingMemory workingMemory) {
+            sink.propagateAssertObject( this.handle,
+                                        this.context,
+                                        workingMemory );
+        }
+    }
+
+    private static class RetractAction extends Action {
+        private static final long serialVersionUID = -84784886430845209L;
+
+        public RetractAction(final InternalFactHandle handle,
+                             final PropagationContext context) {
+            super( handle,
+                   context );
+        }
+
+        public void execute(final ObjectSinkPropagator sink,
+                            final InternalWorkingMemory workingMemory) {
+            sink.propagateRetractObject( this.handle,
+                                         this.context,
+                                         workingMemory,
+                                         true );
+        }
+    }
+
+    /**
+     * This is the action that is added to the working memory actions queue, so that
+     * this node propagation can be triggered at a safe point
+     * 
+     * @author etirelli
+     *
+     */
+    private static class PropagateAction
+        implements
+        WorkingMemoryAction {
+
+        private static final long      serialVersionUID = 6765029029501617115L;
+
+        private PropagationQueuingNode node;
+
+        public PropagateAction(PropagationQueuingNode node) {
+            this.node = node;
+        }
+
+        public void execute(InternalWorkingMemory workingMemory) {
+            this.node.propagateActions( workingMemory );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/QueryTerminalNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/QueryTerminalNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/QueryTerminalNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,225 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.LinkedList;
+
+import org.drools.RuleBaseConfiguration;
+import org.drools.common.BaseNode;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.NodeMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.rule.GroupElement;
+import org.drools.rule.Rule;
+import org.drools.spi.PropagationContext;
+
+/**
+ * Leaf Rete-OO node responsible for enacting <code>Action</code> s on a
+ * matched <code>Rule</code>.
+ * 
+ * @see org.drools.rule.Rule
+ * 
+ * @author <a href="mailto:bob at eng.werken.com">bob mcwhirter </a>
+ */
+public final class QueryTerminalNode extends BaseNode
+    implements
+    TupleSinkNode,
+    NodeMemory,
+    TerminalNode {
+    // ------------------------------------------------------------
+    // Instance members
+    // ------------------------------------------------------------
+
+    /**
+     * 
+     */
+    private static final long  serialVersionUID = 400L;
+    /** The rule to invoke upon match. */
+    private final Rule         rule;
+    private final GroupElement subrule;
+    private final TupleSource  tupleSource;
+    private boolean          tupleMemoryEnabled;    
+    
+    private TupleSinkNode      previousTupleSinkNode;
+    private TupleSinkNode      nextTupleSinkNode;    
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    /**
+     * Construct.
+     * 
+     * @param inputSource
+     *            The parent tuple source.
+     * @param rule
+     *            The rule.
+     */
+    public QueryTerminalNode(final int id,
+                             final TupleSource source,
+                             final Rule rule,
+                             final GroupElement subrule) {
+        super( id );
+        this.rule = rule;
+        this.subrule = subrule;
+        this.tupleSource = source;
+        this.tupleMemoryEnabled = false; //hard coded to false
+    }
+
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+
+    /**
+     * Retrieve the <code>Action</code> associated with this node.
+     * 
+     * @return The <code>Action</code> associated with this node.
+     */
+    public Rule getRule() {
+        return this.rule;
+    }
+
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // org.drools.impl.TupleSink
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+    /**
+     * Assert a new <code>Tuple</code>.
+     * 
+     * @param tuple
+     *            The <code>Tuple</code> being asserted.
+     * @param workingMemory
+     *            The working memory seesion.
+     * @throws AssertionException
+     *             If an error occurs while asserting.
+     */
+    public void assertTuple(final ReteTuple tuple,
+                            final PropagationContext context,
+                            final InternalWorkingMemory workingMemory) {
+        final LinkedList list = (LinkedList) workingMemory.getNodeMemory( this );
+        if ( list.isEmpty() ) {
+            ((ReteooWorkingMemory) workingMemory).setQueryResults( this.rule.getName(),
+                                                                   this );
+        }
+        list.add( tuple );
+    }
+
+    public void retractTuple(final ReteTuple tuple,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+    }
+
+    public String toString() {
+        return "[QueryTerminalNode: rule=" + this.rule.getName() + "]";
+    }
+
+    public void ruleAttached() {
+
+    }
+
+    public void attach() {
+        this.tupleSource.addTupleSink( this );
+    }
+
+    public void attach(final InternalWorkingMemory[] workingMemories) {
+        attach();
+
+        for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+            final InternalWorkingMemory workingMemory = workingMemories[i];
+            final PropagationContext propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
+                                                                                      PropagationContext.RULE_ADDITION,
+                                                                                      null,
+                                                                                      null );
+            this.tupleSource.updateSink( this,
+                                         propagationContext,
+                                         workingMemory );
+        }
+    }
+
+    public void remove(ReteooBuilder builder,
+                       final BaseNode node, final InternalWorkingMemory[] workingMemories) {
+        for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+            workingMemories[i].clearNodeMemory( this );
+        }
+        
+        removeShare(builder);
+        
+        this.tupleSource.remove( builder,
+                                 this, workingMemories );
+    }
+
+    public void updateNewNode(final InternalWorkingMemory workingMemory,
+                              final PropagationContext context) {
+        // There are no child nodes to update, do nothing.
+    }
+
+    public Object createMemory(final RuleBaseConfiguration config) {
+        return new LinkedList();
+    }
+
+    public boolean isTupleMemoryEnabled() {
+        return tupleMemoryEnabled;
+    }
+
+    public void setTupleMemoryEnabled(boolean tupleMemoryEnabled) {
+        this.tupleMemoryEnabled = tupleMemoryEnabled;
+    }
+    
+    /**
+     * @return the subrule
+     */
+    public GroupElement getSubrule() {
+        return this.subrule;
+    }
+    
+    /**
+     * Returns the previous node
+     * @return
+     *      The previous TupleSinkNode
+     */
+    public TupleSinkNode getPreviousTupleSinkNode() {
+        return this.previousTupleSinkNode;
+    }
+
+    /**
+     * Sets the previous node 
+     * @param previous
+     *      The previous TupleSinkNode
+     */
+    public void setPreviousTupleSinkNode(final TupleSinkNode previous) {
+        this.previousTupleSinkNode = previous;
+    }    
+    
+    /**
+     * Returns the next node
+     * @return
+     *      The next TupleSinkNode
+     */
+    public TupleSinkNode getNextTupleSinkNode() {
+        return this.nextTupleSinkNode;
+    }
+
+    /**
+     * Sets the next node 
+     * @param next
+     *      The next TupleSinkNode
+     */
+    public void setNextTupleSinkNode(final TupleSinkNode next) {
+        this.nextTupleSinkNode = next;
+    }    
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/Rete.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/Rete.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/Rete.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,220 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.common.BaseNode;
+import org.drools.common.DroolsObjectInputStream;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalRuleBase;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.EntryPoint;
+import org.drools.spi.ObjectType;
+import org.drools.spi.PropagationContext;
+import org.drools.util.FactEntry;
+import org.drools.util.FactHashTable;
+import org.drools.util.Iterator;
+
+/**
+ * The Rete-OO network.
+ *
+ * The Rete class is the root <code>Object</code>. All objects are asserted into
+ * the Rete node where it propagates to all matching ObjectTypeNodes.
+ *
+ * The first time an  instance of a Class type is asserted it does a full
+ * iteration of all ObjectTyppeNodes looking for matches, any matches are
+ * then cached in a HashMap which is used for future assertions.
+ *
+ * While Rete  extends ObjectSource nad implements ObjectSink it nulls the
+ * methods attach(), remove() and  updateNewNode() as this is the root node
+ * they are no applicable
+ *
+ * @see ObjectTypeNode
+ *
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ */
+public class Rete extends ObjectSource
+    implements
+    Serializable,
+    ObjectSink {
+    // ------------------------------------------------------------
+    // Instance members
+    // ------------------------------------------------------------
+
+    /**
+     *
+     */
+    private static final long                     serialVersionUID = 400L;
+
+    private final Map<EntryPoint, EntryPointNode> entryPoints;
+
+    private transient InternalRuleBase            ruleBase;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    public Rete(InternalRuleBase ruleBase) {
+        super( 0 );
+        this.entryPoints = new HashMap<EntryPoint, EntryPointNode>();
+        this.ruleBase = ruleBase;
+    }
+
+    private void readObject(ObjectInputStream stream) throws IOException,
+                                                     ClassNotFoundException {
+        stream.defaultReadObject();
+        this.ruleBase = ((DroolsObjectInputStream) stream).getRuleBase();
+    }
+
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+
+    /**
+     * This is the entry point into the network for all asserted Facts. Iterates a cache
+     * of matching <code>ObjectTypdeNode</code>s asserting the Fact. If the cache does not
+     * exist it first iteraes and builds the cache.
+     *
+     * @param handle
+     *            The FactHandle of the fact to assert
+     * @param context
+     *            The <code>PropagationContext</code> of the <code>WorkingMemory</code> action
+     * @param workingMemory
+     *            The working memory session.
+     */
+    public void assertObject(final InternalFactHandle handle,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+        EntryPointNode node = this.entryPoints.get( context.getEntryPoint() );
+        node.assertObject( handle,
+                           context,
+                           workingMemory );
+    }
+
+    /**
+     * Retract a fact object from this <code>RuleBase</code> and the specified
+     * <code>WorkingMemory</code>.
+     *
+     * @param handle
+     *            The handle of the fact to retract.
+     * @param workingMemory
+     *            The working memory session.
+     */
+    public void retractObject(final InternalFactHandle handle,
+                              final PropagationContext context,
+                              final InternalWorkingMemory workingMemory) {
+        EntryPointNode node = this.entryPoints.get( context.getEntryPoint() );
+        node.retractObject( handle,
+                            context,
+                            workingMemory );
+    }
+
+    /**
+     * Adds the <code>ObjectSink</code> so that it may receive
+     * <code>Objects</code> propagated from this <code>ObjectSource</code>.
+     *
+     * @param objectSink
+     *            The <code>ObjectSink</code> to receive propagated
+     *            <code>Objects</code>. Rete only accepts <code>ObjectTypeNode</code>s
+     *            as parameters to this method, though.
+     */
+    protected void addObjectSink(final ObjectSink objectSink) {
+        final EntryPointNode node = (EntryPointNode) objectSink;
+        this.entryPoints.put( node.getEntryPoint(),
+                              node );
+    }
+
+    protected void removeObjectSink(final ObjectSink objectSink) {
+        final EntryPointNode node = (EntryPointNode) objectSink;
+        this.entryPoints.remove( node.getEntryPoint() );
+    }
+
+    public void attach() {
+        throw new UnsupportedOperationException( "cannot call attach() from the root Rete node" );
+    }
+
+    public void attach(final InternalWorkingMemory[] workingMemories) {
+        throw new UnsupportedOperationException( "cannot call attach() from the root Rete node" );
+    }
+
+    public void remove(ReteooBuilder builder,
+                       final BaseNode node, final InternalWorkingMemory[] workingMemories) {
+        final EntryPointNode entryPointNode = (EntryPointNode) node;
+        removeObjectSink( entryPointNode );
+    }
+    
+    public EntryPointNode getEntryPointNode( final EntryPoint entryPoint ) {
+        return this.entryPoints.get( entryPoint );
+    }
+
+    public List<ObjectTypeNode> getObjectTypeNodes() {
+        List<ObjectTypeNode> allNodes = new LinkedList<ObjectTypeNode>();
+        for( EntryPointNode node : this.entryPoints.values() ) {
+            allNodes.addAll(node.getObjectTypeNodes().values());
+        }
+        return allNodes;
+    }
+
+    public Map<ObjectType, ObjectTypeNode> getObjectTypeNodes(EntryPoint entryPoint) {
+        return this.entryPoints.get( entryPoint ).getObjectTypeNodes();
+    }
+
+    public InternalRuleBase getRuleBase() {
+        return this.ruleBase;
+    }
+
+    public int hashCode() {
+        return this.entryPoints.hashCode();
+    }
+
+    public boolean equals(final Object object) {
+        if ( object == this ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof Rete) ) {
+            return false;
+        }
+
+        final Rete other = (Rete) object;
+        return this.entryPoints.equals( other.entryPoints );
+    }
+
+    public void updateSink(final ObjectSink sink,
+                           final PropagationContext context,
+                           final InternalWorkingMemory workingMemory) {
+        // nothing to do, since Rete object itself holds no facts to propagate.
+    }
+
+    public boolean isObjectMemoryEnabled() {
+        throw new UnsupportedOperationException( "Rete has no Object memory" );
+    }
+
+    public void setObjectMemoryEnabled(boolean objectMemoryEnabled) {
+        throw new UnsupportedOperationException( "ORete has no Object memory" );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteStatelessSessionResult.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteStatelessSessionResult.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteStatelessSessionResult.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,54 @@
+package org.drools.reteoo;
+
+import java.util.Iterator;
+
+import org.drools.ObjectFilter;
+import org.drools.QueryResults;
+import org.drools.StatelessSessionResult;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.ObjectStore;
+import org.drools.spi.GlobalResolver;
+import org.drools.util.JavaIteratorAdapter;
+import org.drools.util.ObjectHashMap;
+import org.drools.util.AbstractHashTable.HashTableIterator;
+
+public class ReteStatelessSessionResult implements StatelessSessionResult {
+    private transient InternalWorkingMemory workingMemory;
+    // @TODO ObjectStore is currently too heavy for serialisation, but done to fix for now
+    private ObjectStore objectStore;
+    private GlobalResolver globalResolver;
+    
+    public ReteStatelessSessionResult(InternalWorkingMemory workingMemory, GlobalResolver globalResolver) {
+        this.workingMemory = workingMemory;
+        this.objectStore = workingMemory.getObjectStore();
+        this.globalResolver = globalResolver;
+    }
+
+    public QueryResults getQueryResults(String query) {
+        return this.workingMemory.getQueryResults( query );
+    }
+    
+    public QueryResults getQueryResults(final String query, final Object[] arguments) {
+        return this.workingMemory.getQueryResults( query, 
+                                                   arguments );
+    }
+
+    public Iterator iterateObjects() {
+        return this.objectStore.iterateObjects();
+    }
+
+    public Iterator iterateObjects(ObjectFilter filter) {
+        return this.objectStore.iterateObjects( filter );
+    }
+    
+    public Object getGlobal(String identifier) {
+        if ( this.globalResolver == null ) {
+            return null;
+        }
+        return this.globalResolver.resolveGlobal( identifier );
+    }
+    
+    public GlobalResolver getGlobalResolver() {
+        return this.globalResolver;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteTuple.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteTuple.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteTuple.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,287 @@
+package org.drools.reteoo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.base.ShadowProxy;
+import org.drools.common.EventFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.rule.Declaration;
+import org.drools.spi.Activation;
+import org.drools.spi.Tuple;
+import org.drools.util.Entry;
+
+public class ReteTuple
+    implements
+    Tuple,
+    Entry {
+    private static final long        serialVersionUID = 400L;
+
+    private int                      index;
+
+    private final InternalFactHandle handle;
+
+    private ReteTuple                parent;
+
+    private Activation               activation;
+
+    private long                     recency;
+
+    private int                      hashCode;
+    
+    private InternalFactHandle       match;
+
+    private Entry                    next;
+    
+    private boolean 				 containsEvents;
+    
+    //private long			 		 creationTimeFirstContributingEvent;
+    
+    private EventFactHandle 		 firstContributingEvent;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+    public ReteTuple(final InternalFactHandle handle) {
+        this.recency = handle.getRecency();
+        this.handle = handle;
+        int h = handle.hashCode();
+        h += ~(h << 9);
+        h ^= (h >>> 14);
+        h += (h << 4);
+        h ^= (h >>> 10);
+        this.hashCode = h;
+        this.containsEvents = handle.isEvent();
+        //this.creationTimeFirstContributingEvent = (handle.isEvent())?((EventFactHandle)handle).getEndTimestamp():0;
+        this.firstContributingEvent = (handle.isEvent())?((EventFactHandle)handle):null;
+    }
+
+    public ReteTuple(final ReteTuple tuple) {
+        this.index = tuple.index;
+        this.parent = tuple.parent;
+        this.recency = tuple.recency;
+        this.handle = tuple.handle;
+        this.hashCode = tuple.hashCode();
+        this.containsEvents = tuple.containsEvents;
+        //this.creationTimeFirstContributingEvent = (tuple.containsEvents)?tuple.creationTimeFirstContributingEvent:0;
+        this.firstContributingEvent = (tuple.containsEvents)?tuple.firstContributingEvent:null;
+    }
+
+    public ReteTuple(final ReteTuple parentTuple,
+                     final InternalFactHandle handle) {
+        this.index = parentTuple.index + 1;
+        this.parent = parentTuple;
+        this.recency = parentTuple.recency + handle.getRecency();
+        this.handle = handle;
+        this.hashCode = parentTuple.hashCode ^ (handle.hashCode() * 31);
+        this.containsEvents = parentTuple.containsEvents || handle.isEvent();
+       
+    	/*if (parentTuple.containsEvents){
+    		if (handle.isEvent())
+    			this.creationTimeFirstContributingEvent = Math.min(((EventFactHandle)handle).getEndTimestamp(), parentTuple.creationTimeFirstContributingEvent);
+    		else this.creationTimeFirstContributingEvent = parentTuple.creationTimeFirstContributingEvent;
+    	}
+    	else{
+    		if (handle.isEvent())
+    			this.creationTimeFirstContributingEvent = ((EventFactHandle)handle).getEndTimestamp();
+    		else this.creationTimeFirstContributingEvent = 0;
+    	}*/
+        
+        
+        
+        if (handle.isEvent()){
+        	EventFactHandle evHandle = ((EventFactHandle)handle);
+        	if (parentTuple.containsEvents && (parentTuple.firstContributingEvent.getEndTimestamp()<evHandle.getEndTimestamp()))
+        		this.firstContributingEvent = parentTuple.firstContributingEvent;
+        	else this.firstContributingEvent = evHandle;
+        } else {
+        	if (parentTuple.containsEvents())
+        		this.firstContributingEvent = parentTuple.firstContributingEvent;
+        	else this.firstContributingEvent = null;
+        }
+        
+        /*if (parentTuple.containsEvents){
+    		if (handle.isEvent() && (evHandle.getEndTimestamp()<parentTuple.firstContributingEvent.getEndTimestamp()))
+    			this.firstContributingEvent = evHandle;
+    		else this.firstContributingEvent = parentTuple.firstContributingEvent;
+    	}
+    	else{
+    		if (handle.isEvent())
+    			this.firstContributingEvent = evHandle;
+    		else this.firstContributingEvent = null;
+    	}*/
+    }
+
+    public InternalFactHandle get(final int index) {
+        ReteTuple entry = this;
+        while ( entry.index != index ) {
+            entry = entry.parent;
+        }
+        return entry.handle;
+    }
+
+    public void setNext(final Entry next) {
+        this.next = next;
+    }
+
+    public Entry getNext() {
+        return this.next;
+    }
+
+    public InternalFactHandle getLastHandle() {
+        return this.handle;
+    }
+
+    public InternalFactHandle get(final Declaration declaration) {
+        return get( declaration.getPattern().getOffset() );
+    }
+
+    public Activation getActivation() {
+        return this.activation;
+    }
+
+    /**
+     * Returns the fact handles in reverse order
+     */
+    public InternalFactHandle[] getFactHandles() {
+        final List list = new ArrayList();
+        ReteTuple entry = this;
+        while ( entry != null ) {
+            list.add( entry.handle );
+            entry = entry.parent;
+        }
+
+        return (InternalFactHandle[]) list.toArray( new InternalFactHandle[list.size()] );
+    }
+
+    public long getRecency() {
+        return this.recency;
+    }
+        
+
+    public InternalFactHandle getMatch() {
+        return match;
+    }
+
+    public void setMatch(InternalFactHandle match) {
+        this.match = match;
+    }
+
+    public void setActivation(final Activation activation) {
+        this.activation = activation;
+    }
+
+    public int hashCode() {
+        return this.hashCode;
+    }
+
+    public String toString() {
+        final StringBuffer buffer = new StringBuffer();
+
+        ReteTuple entry = this;
+        while ( entry != null ) {
+            //buffer.append( entry.handle );
+            buffer.append( entry.handle + "\n" );
+            entry = entry.parent;
+        }
+        return buffer.toString();
+    }
+
+    /**
+     * We use this equals method to avoid the cast
+     * @param tuple
+     * @return
+     */
+    public boolean equals(final ReteTuple other) {
+        // we know the object is never null and always of the  type ReteTuple
+        if ( other == this ) {
+            return true;
+        }
+
+        // A ReteTuple is  only the same if it has the same hashCode, factId and parent
+        if ( (other == null) || (this.hashCode != other.hashCode) ) {
+            return false;
+        }
+
+        if ( this.handle != other.handle ) {
+            return false;
+        }
+
+        if ( this.parent == null ) {
+            return (other.parent == null);
+        } else {
+            return this.parent.equals( other.parent );
+        }
+    }
+
+    public boolean equals(final Object object) {
+        // we know the object is never null and always of the  type ReteTuple    
+        return equals( (ReteTuple) object );
+    }
+
+    public int size() {
+        return this.index + 1;
+    }
+
+    /**
+     * Returns the ReteTuple that contains the "elements"
+     * first elements in this tuple.
+     * 
+     * Use carefully as no cloning is made during this process.
+     * 
+     * This method is used by TupleStartEqualsConstraint when
+     * joining a subnetwork tuple into the main network tuple;
+     * 
+     * @param elements the number of elements to return, starting from
+     * the begining of the tuple
+     * 
+     * @return a ReteTuple containing the "elements" first elements
+     * of this tuple or null if "elements" is greater than size; 
+     */
+    public ReteTuple getSubTuple(final int elements) {
+        ReteTuple entry = this;
+        if ( elements < this.size() ) {
+            final int lastindex = elements - 1;
+
+            while ( entry.index != lastindex ) {
+                entry = entry.parent;
+            }
+        }
+        return entry;
+    }
+    
+    public Object[] toObjectArray() {        
+        Object[] objects = new Object[ this.index + 1 ];
+        ReteTuple entry = this;       
+        while ( entry != null ) {
+            Object object = entry.getLastHandle().getObject();
+            if ( object instanceof ShadowProxy ) {
+                object = ((ShadowProxy)object).getShadowedObject();
+            }
+            objects[entry.index] = object;
+            entry = entry.parent;
+        }   
+        return objects;
+    }
+
+	@Override
+	public boolean containsEvents() {
+		return containsEvents;
+	}
+	
+	public boolean firstContributingEventStillPresent(){
+		return firstContributingEvent != null;
+	}
+
+	//@Override
+	public long getCreationTimeFirstContributingEvent() {
+		//return creationTimeFirstContributingEvent;
+		try {
+			return firstContributingEvent.getEndTimestamp();
+		} catch (NullPointerException e) {
+			System.err.println ("First contributing of tuple "+this.toString()+" event not present anymore (probably expired)"); 
+			e.printStackTrace();
+			return Long.MIN_VALUE;
+		} 
+	}
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooBuilder.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooBuilder.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooBuilder.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,278 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.drools.RuleIntegrationException;
+import org.drools.base.SalienceInteger;
+import org.drools.common.BaseNode;
+import org.drools.common.DroolsObjectInputStream;
+import org.drools.common.InternalRuleBase;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.builder.ReteooRuleBuilder;
+import org.drools.rule.InvalidPatternException;
+import org.drools.rule.Rule;
+import org.drools.spi.Salience;
+
+/**
+ * Builds the Rete-OO network for a <code>Package</code>.
+ * 
+ * @see org.drools.rule.Package
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ * 
+ */
+public class ReteooBuilder
+    implements
+    Serializable {
+    // ------------------------------------------------------------
+    // Instance members
+    // ------------------------------------------------------------
+
+    /**
+     * 
+     */
+    private static final long                 serialVersionUID = 400L;
+
+    /** The RuleBase */
+    private transient InternalRuleBase        ruleBase;
+
+    private transient InternalWorkingMemory[] workingMemories;
+
+    private Map                               rules;
+
+    private transient ReteooRuleBuilder       ruleBuilder;
+
+    private IdGenerator                       idGenerator;
+
+    private boolean                           ordered;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    /**
+     * Construct a <code>Builder</code> against an existing <code>Rete</code>
+     * network.
+     */
+    ReteooBuilder(final InternalRuleBase ruleBase) {
+        this.ruleBase = ruleBase;
+        this.rules = new HashMap();
+
+        //Set to 1 as Rete node is set to 0
+        this.idGenerator = new IdGenerator( 1 );
+        this.ruleBuilder = new ReteooRuleBuilder();
+    }
+
+    private void readObject(ObjectInputStream stream) throws IOException,
+                                                     ClassNotFoundException {
+        stream.defaultReadObject();
+        this.ruleBase = ((DroolsObjectInputStream) stream).getRuleBase();
+        this.ruleBuilder = new ReteooRuleBuilder();
+    }
+
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+
+    /**
+     * Add a <code>Rule</code> to the network.
+     * 
+     * @param rule
+     *            The rule to add.
+     * 
+     * @throws RuleIntegrationException
+     *             if an error prevents complete construction of the network for
+     *             the <code>Rule</code>.
+     * @throws InvalidPatternException
+     */
+    void addRule(final Rule rule) throws InvalidPatternException {
+        final List terminals = this.ruleBuilder.addRule( rule,
+                                                         this.ruleBase,
+                                                         this.idGenerator );
+
+        this.rules.put( rule,
+                        terminals.toArray( new BaseNode[terminals.size()] ) );
+    }
+
+    public IdGenerator getIdGenerator() {
+        return this.idGenerator;
+    }
+
+    public void order() {
+        if ( ordered ) {
+            // we should only do this on first call, its expected the RuleBase should not change afterwards.
+            return;
+        }
+        Map map = new HashMap();
+
+        for ( Iterator it = this.rules.values().iterator(); it.hasNext(); ) {
+            BaseNode[] nodes = (BaseNode[]) it.next();
+            for ( int i = 0; i < nodes.length; i++ ) {
+                if ( nodes[i] instanceof RuleTerminalNode ) {
+                    RuleTerminalNode node = (RuleTerminalNode) nodes[i];
+                    String agendaGroup = node.getRule().getAgendaGroup();
+                    if ( agendaGroup == null || agendaGroup.equals( "" ) ) {
+                        agendaGroup = "MAIN";
+                    }
+                    List rules = (List) map.get( agendaGroup );
+                    if ( rules == null ) {
+                        rules = new ArrayList();
+                        map.put( agendaGroup,
+                                 rules );
+                    }
+                    rules.add( node );
+                }
+            }
+        }
+
+        for ( Iterator it = map.entrySet().iterator(); it.hasNext(); ) {
+            Entry entry = (Entry) it.next();
+            String agendaGroup = (String) entry.getKey();
+            List rules = (List) entry.getValue();
+            Collections.sort( rules,
+                              RuleSequenceComparator.INSTANCE );
+
+            int i = 0;
+            for ( Iterator listIter = rules.iterator(); listIter.hasNext(); ) {
+                RuleTerminalNode node = (RuleTerminalNode) listIter.next();
+                node.setSequence( i++ );
+            }
+
+            ruleBase.getAgendaGroupRuleTotals().put( agendaGroup,
+                                                     new Integer( i ) );
+        }
+        ordered = true;
+    }
+
+    public static class RuleSequenceComparator
+        implements
+        Comparator {
+        public final static RuleSequenceComparator INSTANCE = new RuleSequenceComparator();
+
+        public int compare(Object o1,
+                           Object o2) {
+            RuleTerminalNode r1 = (RuleTerminalNode) o1;
+            RuleTerminalNode r2 = (RuleTerminalNode) o2;
+
+            Salience so1 = r1.getRule().getSalience();
+            if ( so1 != null && !(so1 instanceof SalienceInteger) ) {
+                throw new RuntimeException( r1.getRule().getName() + "must not have a dynamic salience" );
+            }
+            Salience so2 = r2.getRule().getSalience();
+            if ( so2 != null && !(so2 instanceof SalienceInteger) ) {
+                throw new RuntimeException( r2.getRule().getName() + "must not have a dynamic salience" );
+            }
+
+            int s1 = so1.getValue( null,
+                                   null );
+            int s2 = so2.getValue( null,
+                                   null );
+
+            if ( s1 > s2 ) {
+                return -1;
+            } else if ( s1 < s2 ) {
+                return 1;
+            }
+
+            int id1 = r1.getId();
+            int id2 = r2.getId();
+
+            if ( id1 < id2 ) {
+                return -1;
+            } else if ( id1 > id2 ) {
+                return 1;
+            } else {
+                return 0;
+            }
+        }
+
+    }
+
+    public BaseNode[] getTerminalNodes(final Rule rule) {
+        return (BaseNode[]) this.rules.get( rule );
+    }
+
+    public void removeRule(final Rule rule) {
+        // reset working memories for potential propagation
+        this.workingMemories = (InternalWorkingMemory[]) this.ruleBase.getWorkingMemories();
+
+        final Object object = this.rules.remove( rule );
+
+        final BaseNode[] nodes = (BaseNode[]) object;
+        for ( int i = 0, length = nodes.length; i < length; i++ ) {
+            final BaseNode node = nodes[i];
+            node.remove( this,
+                         null,
+                         this.workingMemories );
+        }
+    }
+
+    public static class IdGenerator
+        implements
+        Serializable {
+
+        private static final long serialVersionUID = 400L;
+
+        private Queue<Integer>    recycledIds;
+        private int               nextId;
+
+        public IdGenerator(final int firstId) {
+            this.nextId = firstId;
+            this.recycledIds = new LinkedList<Integer>();
+        }
+
+        public int getNextId() {
+            Integer id = this.recycledIds.poll();
+            if( id == null ) {
+                return this.nextId++;
+            }
+            return id.intValue();
+        }
+
+        public void releaseLastId() {
+            this.nextId--;
+        }
+        
+        public void releaseId( int id ) {
+            this.recycledIds.add( new Integer(id) );
+        }
+
+        public int getLastId() {
+            return this.nextId-1;
+        }
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooFactHandleFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooFactHandleFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooFactHandleFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,75 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.TemporalSession;
+import org.drools.WorkingMemory;
+import org.drools.common.AbstractFactHandleFactory;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.EventFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.spi.FactHandleFactory;
+import org.drools.temporal.SessionClock;
+
+public class ReteooFactHandleFactory extends AbstractFactHandleFactory {
+
+    private static final long serialVersionUID = 400L;
+
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.FactHandleFactory#newFactHandle(long)
+     */
+    protected final InternalFactHandle newFactHandle(final long id,
+                                                     final Object object,
+                                                     final long recency,
+                                                     final boolean isEvent,
+                                                     final WorkingMemory workingMemory ) {
+        
+    	SessionClock clock = ((TemporalSession) workingMemory).getSessionClock();
+    	return newFactHandle (id, object, recency, isEvent, clock.getCurrentTime(), workingMemory);
+   
+    }
+    
+    protected final InternalFactHandle newFactHandle(final long id,
+										             final Object object,
+										             final long recency,
+										             final boolean isEvent,
+										             final long clockTime,
+										             final WorkingMemory workingMemory ) {
+		if ( isEvent ) {
+			return new EventFactHandle( id,
+										object,
+										recency,
+										clockTime,
+										0 );  // primitive events have 0 duration
+		} else {
+			return new DefaultFactHandle( id,
+										  object,
+										  recency );
+		}
+	}
+    
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.FactHandleFactory#newInstance()
+     */
+    public FactHandleFactory newInstance() {
+        return new ReteooFactHandleFactory();
+    }
+
+    public Class getFactHandleType() {
+        return DefaultFactHandle.class;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooRuleBase.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooRuleBase.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooRuleBase.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,343 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Observer;
+import java.util.Set;
+
+import org.drools.ClockType;
+import org.drools.FactException;
+import org.drools.FactHandle;
+import org.drools.RuleBase;
+import org.drools.RuleBaseConfiguration;
+import org.drools.StatefulSession;
+import org.drools.StatelessSession;
+import org.drools.TemporalSession;
+import org.drools.common.AbstractRuleBase;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.concurrent.CommandExecutor;
+import org.drools.concurrent.ExecutorService;
+import org.drools.event.RuleBaseEventListener;
+import org.drools.reteoo.ReteooWorkingMemory.WorkingMemoryReteAssertAction;
+import org.drools.rule.EntryPoint;
+import org.drools.rule.InvalidPatternException;
+import org.drools.rule.Package;
+import org.drools.rule.Rule;
+import org.drools.spi.ExecutorServiceFactory;
+import org.drools.spi.FactHandleFactory;
+import org.drools.spi.PropagationContext;
+import org.drools.temporal.GlobalSessionClockImpl;
+
+/**
+ * Implementation of <code>RuleBase</code>.
+ * 
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter</a>
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a> 
+ * 
+ * @version $Id: RuleBaseImpl.java,v 1.5 2005/08/14 22:44:12 mproctor Exp $
+ */
+public class ReteooRuleBase extends AbstractRuleBase {
+    /**
+     * DO NOT CHANGE BELLOW SERIAL_VERSION_ID UNLESS YOU ARE CHANGING DROOLS VERSION
+     * SERIAL_VERSION_ID=320 stands for version 3.2.0 
+     */
+    private static final long serialVersionUID = 400L;
+
+    /** The root Rete-OO for this <code>RuleBase</code>. */
+    private transient Rete    rete;
+
+    private ReteooBuilder     reteooBuilder;
+    
+    //private Set<Observer> clockInitializedObservers;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    /**
+     * Default constructor - for Externalizable. This should never be used by a user, as it 
+     * will result in an invalid state for the instance.
+     */
+    public ReteooRuleBase() {
+
+    }
+
+    /**
+     * Construct.
+     * 
+     * @param rete
+     *            The rete network.
+     */
+    public ReteooRuleBase(final String id) {
+        this( id,
+              null,
+              new ReteooFactHandleFactory() );
+    }
+
+    /**
+     * @param factHandleFactory
+     */
+    public ReteooRuleBase(final String id,
+                          final FactHandleFactory factHandleFactory) {
+        this( id,
+              null,
+              factHandleFactory );
+    }
+
+    public ReteooRuleBase(final String id,
+                          final RuleBaseConfiguration config) {
+        this( id,
+              config,
+              new ReteooFactHandleFactory() );
+    }
+
+    /**
+     * @param config
+     */
+    public ReteooRuleBase(final RuleBaseConfiguration config) {
+        this( null,
+              config,
+              new ReteooFactHandleFactory() );
+    }
+
+    /**
+     * Construct.
+     * 
+     * @param rete
+     *            The rete network.
+     */
+    public ReteooRuleBase(final String id,
+                          final RuleBaseConfiguration config,
+                          final FactHandleFactory factHandleFactory) {
+        super( id,
+               config,
+               factHandleFactory );
+        this.rete = new Rete( this );
+        this.reteooBuilder = new ReteooBuilder( this );
+        
+        // always add the default entry point
+        EntryPointNode epn = new EntryPointNode( this.reteooBuilder.getIdGenerator().getNextId(), 
+                                                 this.rete,
+                                                 EntryPoint.DEFAULT );
+        epn.attach();
+        
+        //this.clockInitializedObservers = new HashSet<Observer>();
+        
+    }
+
+    /**
+     * Handles the write serialization of the Package. Patterns in Rules may reference generated data which cannot be serialized by default methods.
+     * The Package uses PackageCompilationData to hold a reference to the generated bytecode. The generated bytecode must be restored before any Rules.
+     * 
+     */
+    public void writeExternal(final ObjectOutput stream) throws IOException {
+        doWriteExternal( stream );
+    }
+
+    /**
+     * Handles the read serialization of the Package. Patterns in Rules may reference generated data which cannot be serialized by default methods.
+     * The Package uses PackageCompilationData to hold a reference to the generated bytecode; which must be restored before any Rules.
+     * A custom ObjectInputStream, able to resolve classes against the bytecode in the PackageCompilationData, is used to restore the Rules.
+     * 
+     */
+    public void readExternal(final ObjectInput stream) throws IOException,
+                                                      ClassNotFoundException {
+        doReadExternal( stream );
+
+        // rebuild the Rete network from the pkg information
+        this.reteooBuilder = new ReteooBuilder( this );
+        this.rete = new Rete( this );
+        synchronized ( this.pkgs ) {
+            for ( Package pkg : this.pkgs.values() ) {
+                for ( Rule rule : pkg.getRules() ) {
+                    addRule( rule );
+                }
+            }
+        }
+    }
+
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+
+    /**
+     * Retrieve the Rete-OO network for this <code>RuleBase</code>.
+     * 
+     * @return The RETE-OO network.
+     */
+    public Rete getRete() {
+        return this.rete;
+    }
+
+    public ReteooBuilder getReteooBuilder() {
+        return this.reteooBuilder;
+    }
+
+    /**
+     * Assert a fact object.
+     * 
+     * @param handle
+     *            The handle.
+     * @param object
+     *            The fact.
+     * @param workingMemory
+     *            The working-memory.
+     * 
+     * @throws FactException
+     *             If an error occurs while performing the assertion.
+     */
+    public void assertObject(final FactHandle handle,
+                             final Object object,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) throws FactException {
+        getRete().assertObject( (DefaultFactHandle) handle,
+                                context,
+                                workingMemory );
+    }
+
+    /**
+     * Retract a fact object.
+     * 
+     * @param handle
+     *            The handle.
+     * @param workingMemory
+     *            The working-memory.
+     * 
+     * @throws FactException
+     *             If an error occurs while performing the retraction.
+     */
+    public void retractObject(final FactHandle handle,
+                              final PropagationContext context,
+                              final ReteooWorkingMemory workingMemory) throws FactException {
+        getRete().retractObject( (InternalFactHandle) handle,
+                                 context,
+                                 workingMemory );
+    }
+
+    public synchronized StatefulSession newStatefulSession(final boolean keepReference) {
+        return newStatefulSession( keepReference,
+                                   null );
+    }
+
+    public synchronized TemporalSession newTemporalSession(final ClockType clockType) {
+        return (TemporalSession) newStatefulSession( true,
+                                                     clockType );
+    }
+
+    public synchronized TemporalSession newTemporalSession(final boolean keepReference,
+                                                           final ClockType clockType) {
+        return (TemporalSession) newStatefulSession( keepReference,
+                                                     clockType );
+    }
+
+    /**
+     * @see RuleBase
+     */
+    private StatefulSession newStatefulSession(final boolean keepReference,
+                                               final ClockType clockType) {
+        if ( this.config.isSequential() ) {
+            throw new RuntimeException( "Cannot have a stateful rule session, with sequential configuration set to true" );
+        }
+        ReteooStatefulSession session = null;
+
+        synchronized ( this.pkgs ) {
+            ExecutorService executor = ExecutorServiceFactory.createExecutorService( this.config.getExecutorService() );;
+            if ( clockType == null ) {
+                session = new ReteooStatefulSession( nextWorkingMemoryCounter(),
+                                                     this,
+                                                     executor );
+            } else {
+                session = new ReteooTemporalSession( nextWorkingMemoryCounter(),
+                                                     this,
+                                                     executor,
+                                                     GlobalSessionClockImpl.createInstance(clockType) );
+            }
+
+            executor.setCommandExecutor( new CommandExecutor( session ) );
+
+            if ( keepReference ) {
+                super.addStatefulSession( session );
+                for ( Iterator it = session.getRuleBaseUpdateListeners().iterator(); it.hasNext(); ) {
+                    addEventListener( (RuleBaseEventListener) it.next() );
+                }
+            }
+
+            final InitialFactHandle handle = new InitialFactHandle( session.getFactHandleFactory().newFactHandle( new InitialFactHandleDummyObject(),
+                                                                                                                  false,
+                                                                                                                  session ) );
+
+            session.queueWorkingMemoryAction( new WorkingMemoryReteAssertAction( handle,
+                                                                                 false,
+                                                                                 true,
+                                                                                 null,
+                                                                                 null ) );
+        }
+
+        return session;
+    }
+
+    public StatelessSession newStatelessSession() {
+
+        //orders the rules
+        if ( this.config.isSequential() ) {
+            this.reteooBuilder.order();
+        }
+
+        synchronized ( this.pkgs ) {
+            return new ReteooStatelessSession( this );
+        }
+    }
+
+    protected synchronized void addRule(final Rule rule) throws InvalidPatternException {
+        // This adds the rule. ReteBuilder has a reference to the WorkingMemories and will propagate any existing facts.
+        this.reteooBuilder.addRule( rule );
+    }
+
+    protected synchronized void removeRule(final Rule rule) {
+        this.reteooBuilder.removeRule( rule );
+    }
+    
+    public int getNodeCount() {
+        return this.reteooBuilder.getIdGenerator().getLastId();
+    }
+
+    public static class InitialFactHandleDummyObject
+        implements
+        Serializable {
+        private static final long serialVersionUID = 400L;
+    }
+
+	/*@Override
+	public synchronized void addClockInitializedObserver(Observer myObserver) {
+		this.clockInitializedObservers.add(myObserver);
+		
+	}
+
+	@Override
+	public Set<Observer> getClockInitializedObservers() {
+		return this.clockInitializedObservers;
+	}*/
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooStatefulSession.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooStatefulSession.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooStatefulSession.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,105 @@
+package org.drools.reteoo;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.drools.FactHandle;
+import org.drools.StatefulSession;
+import org.drools.common.InternalRuleBase;
+import org.drools.concurrent.AssertObject;
+import org.drools.concurrent.AssertObjects;
+import org.drools.concurrent.ExecutorService;
+import org.drools.concurrent.FireAllRules;
+import org.drools.concurrent.Future;
+import org.drools.concurrent.RetractObject;
+import org.drools.concurrent.UpdateObject;
+import org.drools.event.RuleBaseEventListener;
+import org.drools.spi.AgendaFilter;
+import org.drools.spi.RuleBaseUpdateListener;
+import org.drools.spi.RuleBaseUpdateListenerFactory;
+
+public class ReteooStatefulSession extends ReteooWorkingMemory
+    implements
+    StatefulSession {
+
+    private static final long serialVersionUID = -5360554247241558374L;
+    private transient ExecutorService executor;
+    
+    private transient List                          ruleBaseListeners;
+
+    public ReteooStatefulSession(final int id,
+                                 final InternalRuleBase ruleBase,
+                                 final ExecutorService executorService) {
+        super( id,
+               ruleBase );
+        this.executor = executorService;
+    }
+
+    public Future asyncInsert(final Object object) {
+        final AssertObject assertObject = new AssertObject( object );
+        this.executor.submit( assertObject );
+        return assertObject;
+    }
+
+    public Future asyncRetract(final FactHandle factHandle) {
+        return this.executor.submit( new RetractObject( factHandle ) );
+    }
+
+    public Future asyncUpdate(final FactHandle factHandle,
+                                    final Object object) {
+        return this.executor.submit( new UpdateObject( factHandle,
+                                                       object ) );
+    }
+
+    public Future asyncInsert(final Object[] array) {
+        final AssertObjects assertObjects = new AssertObjects( array );
+        this.executor.submit( assertObjects );
+        return assertObjects;
+    }
+
+    public Future asyncInsert(final Collection collection) {
+        final AssertObjects assertObjects = new AssertObjects( collection );
+        this.executor.submit( assertObjects );
+        return assertObjects;
+    }
+
+    public Future asyncFireAllRules(final AgendaFilter agendaFilter) {
+        final FireAllRules fireAllRules = new FireAllRules( agendaFilter );
+        this.executor.submit( fireAllRules );
+        return fireAllRules;
+    }
+
+    public Future asyncFireAllRules() {
+        final FireAllRules fireAllRules = new FireAllRules( null );
+        this.executor.submit( fireAllRules );
+        return fireAllRules;
+    }
+    
+    public void dispose() {
+        this.ruleBase.disposeStatefulSession( this );
+        this.workingMemoryEventSupport.reset();
+        this.agendaEventSupport.reset();
+        this.workflowEventSupport.reset();
+        for( Iterator it = this.__ruleBaseEventListeners.iterator(); it.hasNext(); ) {
+            this.ruleBase.removeEventListener( (RuleBaseEventListener) it.next() );
+        }
+        this.executor.shutDown();
+    }
+
+    public List getRuleBaseUpdateListeners() {
+        if ( this.ruleBaseListeners == null || this.ruleBaseListeners == Collections.EMPTY_LIST ) {
+            String listenerName = this.ruleBase.getConfiguration().getRuleBaseUpdateHandler();
+            if ( listenerName != null && listenerName.length() > 0 ) {
+                RuleBaseUpdateListener listener = RuleBaseUpdateListenerFactory.createListener( listenerName,
+                                                                                                this );
+                this.ruleBaseListeners = Collections.singletonList( listener );
+            } else {
+                this.ruleBaseListeners = Collections.EMPTY_LIST;
+            }
+        }
+        return this.ruleBaseListeners;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooStatelessSession.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooStatelessSession.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooStatelessSession.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,240 @@
+package org.drools.reteoo;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.drools.StatelessSession;
+import org.drools.StatelessSessionResult;
+import org.drools.base.MapGlobalResolver;
+import org.drools.common.InternalRuleBase;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.concurrent.AssertObject;
+import org.drools.concurrent.AssertObjects;
+import org.drools.concurrent.CommandExecutor;
+import org.drools.concurrent.ExecutorService;
+import org.drools.concurrent.FireAllRules;
+import org.drools.event.AgendaEventListener;
+import org.drools.event.AgendaEventSupport;
+import org.drools.event.RuleBaseEventListener;
+import org.drools.event.RuleFlowEventListener;
+import org.drools.event.RuleFlowEventSupport;
+import org.drools.event.WorkingMemoryEventListener;
+import org.drools.event.WorkingMemoryEventSupport;
+import org.drools.reteoo.ReteooRuleBase.InitialFactHandleDummyObject;
+import org.drools.reteoo.ReteooWorkingMemory.WorkingMemoryReteAssertAction;
+import org.drools.spi.AgendaFilter;
+import org.drools.spi.ExecutorServiceFactory;
+import org.drools.spi.GlobalExporter;
+import org.drools.spi.GlobalResolver;
+
+public class ReteooStatelessSession
+    implements
+    StatelessSession {
+    //private WorkingMemory workingMemory;
+
+    private InternalRuleBase            ruleBase;
+    private AgendaFilter                agendaFilter;
+    private GlobalResolver              globalResolver            = new MapGlobalResolver();
+    
+    private GlobalExporter              globalExporter;
+
+    /** The eventSupport */
+    protected WorkingMemoryEventSupport workingMemoryEventSupport = new WorkingMemoryEventSupport();
+
+    protected AgendaEventSupport        agendaEventSupport        = new AgendaEventSupport();
+
+    protected RuleFlowEventSupport      ruleFlowEventSupport      = new RuleFlowEventSupport();
+
+    public ReteooStatelessSession(final InternalRuleBase ruleBase) {
+        this.ruleBase = ruleBase;
+    }
+
+    public InternalWorkingMemory newWorkingMemory() {
+        synchronized ( this.ruleBase.getPackagesMap() ) {
+            InternalWorkingMemory wm = new ReteooWorkingMemory( this.ruleBase.nextWorkingMemoryCounter(),
+                                                                this.ruleBase );
+
+            wm.setGlobalResolver( this.globalResolver );
+            wm.setWorkingMemoryEventSupport( this.workingMemoryEventSupport );
+            wm.setAgendaEventSupport( this.agendaEventSupport );
+            wm.setRuleFlowEventSupport( ruleFlowEventSupport );
+
+            final InitialFactHandle handle = new InitialFactHandle( wm.getFactHandleFactory().newFactHandle( new InitialFactHandleDummyObject(), false, wm ) );
+
+            wm.queueWorkingMemoryAction( new WorkingMemoryReteAssertAction( handle,
+                                                                            false,
+                                                                            true,
+                                                                            null,
+                                                                            null ) );
+            return wm;
+        }
+    }
+
+    public void addEventListener(final WorkingMemoryEventListener listener) {
+        this.workingMemoryEventSupport.addEventListener( listener );
+    }
+
+    public void removeEventListener(final WorkingMemoryEventListener listener) {
+        this.workingMemoryEventSupport.removeEventListener( listener );
+    }
+
+    public List getWorkingMemoryEventListeners() {
+        return this.workingMemoryEventSupport.getEventListeners();
+    }
+
+    public void addEventListener(final AgendaEventListener listener) {
+        this.agendaEventSupport.addEventListener( listener );
+    }
+
+    public void removeEventListener(final AgendaEventListener listener) {
+        this.agendaEventSupport.removeEventListener( listener );
+    }
+
+    public List getAgendaEventListeners() {
+        return this.agendaEventSupport.getEventListeners();
+    }
+
+    public void addEventListener(final RuleFlowEventListener listener) {
+        this.ruleFlowEventSupport.addEventListener( listener );
+    }
+
+    public void removeEventListener(final RuleFlowEventListener listener) {
+        this.ruleFlowEventSupport.removeEventListener( listener );
+    }
+
+    public List getRuleFlowEventListeners() {
+        return this.ruleFlowEventSupport.getEventListeners();
+    }
+    
+    public void addEventListener(RuleBaseEventListener listener) {
+        this.ruleBase.addEventListener( listener );
+    }
+
+    public List getRuleBaseEventListeners() {
+        return this.ruleBase.getRuleBaseEventListeners();
+    }
+
+    public void removeEventListener(RuleBaseEventListener listener) {
+        this.ruleBase.removeEventListener( listener );
+    }
+
+    public void setAgendaFilter(AgendaFilter agendaFilter) {
+        this.agendaFilter = agendaFilter;
+    }
+
+    public void setGlobal(String identifier,
+                          Object value) {
+        this.globalResolver.setGlobal( identifier,
+                                       value );
+    }
+
+    public void setGlobalResolver(GlobalResolver globalResolver) {
+        this.globalResolver = globalResolver;
+    }
+    
+    public void setGlobalExporter(GlobalExporter globalExporter) {
+        this.globalExporter = globalExporter;
+    }
+
+    public void execute(Object object) {
+        InternalWorkingMemory wm = newWorkingMemory();
+
+        wm.insert( object );
+        wm.fireAllRules( this.agendaFilter );
+    }
+
+    public void execute(Object[] array) {
+        InternalWorkingMemory wm = newWorkingMemory();
+
+        for ( int i = 0, length = array.length; i < length; i++ ) {
+            wm.insert( array[i] );
+        }
+        wm.fireAllRules( this.agendaFilter );
+    }
+
+    public void execute(Collection collection) {
+        InternalWorkingMemory wm = newWorkingMemory();
+
+        for ( Iterator it = collection.iterator(); it.hasNext(); ) {
+            wm.insert( it.next() );
+        }
+        wm.fireAllRules( this.agendaFilter );
+    }
+
+    public void asyncExecute(final Object object) {
+        InternalWorkingMemory wm = newWorkingMemory();
+
+        final AssertObject assertObject = new AssertObject( object );
+        ExecutorService executor = ExecutorServiceFactory.createExecutorService(  this.ruleBase.getConfiguration().getExecutorService() );
+        executor.setCommandExecutor( new CommandExecutor( wm ) );
+        executor.submit( assertObject );
+        executor.submit( new FireAllRules( this.agendaFilter ) );
+    }
+
+    public void asyncExecute(final Object[] array) {
+        InternalWorkingMemory wm = newWorkingMemory();
+
+        final AssertObjects assertObjects = new AssertObjects( array );
+        ExecutorService executor = ExecutorServiceFactory.createExecutorService(  this.ruleBase.getConfiguration().getExecutorService() );
+        executor.setCommandExecutor( new CommandExecutor( wm ) );
+        executor.submit( assertObjects );
+        executor.submit( new FireAllRules( this.agendaFilter ) );
+    }
+
+    public void asyncExecute(final Collection collection) {
+        InternalWorkingMemory wm = newWorkingMemory();
+
+        final AssertObjects assertObjects = new AssertObjects( collection );
+        ExecutorService executor = ExecutorServiceFactory.createExecutorService(  this.ruleBase.getConfiguration().getExecutorService() );
+        executor.setCommandExecutor( new CommandExecutor( wm ) );
+        executor.submit( assertObjects );
+        executor.submit( new FireAllRules( this.agendaFilter ) );
+    }
+
+    public StatelessSessionResult executeWithResults(Object object) {
+        InternalWorkingMemory wm = newWorkingMemory();
+
+        wm.insert( object );
+        wm.fireAllRules( this.agendaFilter );
+        
+        GlobalResolver globalResolver = null;
+        if ( this.globalExporter != null ) {
+            globalResolver = this.globalExporter.export( wm );
+        }
+        return new ReteStatelessSessionResult( wm,
+                                               globalResolver );
+    }
+
+    public StatelessSessionResult executeWithResults(Object[] array) {
+        InternalWorkingMemory wm = newWorkingMemory();
+
+        for ( int i = 0, length = array.length; i < length; i++ ) {
+            wm.insert( array[i] );
+        }
+        wm.fireAllRules( this.agendaFilter );
+        
+        GlobalResolver globalResolver = null;
+        if ( this.globalExporter != null ) {
+            globalResolver = this.globalExporter.export( wm );
+        }
+        return new ReteStatelessSessionResult( wm,
+                                               globalResolver );
+    }
+
+    public StatelessSessionResult executeWithResults(Collection collection) {
+        InternalWorkingMemory wm = newWorkingMemory();
+
+        for ( Iterator it = collection.iterator(); it.hasNext(); ) {
+            wm.insert( it.next() );
+        }
+        wm.fireAllRules( this.agendaFilter );
+
+        GlobalResolver globalResolver = null;
+        if ( this.globalExporter != null ) {
+            globalResolver = this.globalExporter.export( wm );
+        }
+        return new ReteStatelessSessionResult( wm,
+                                               globalResolver );        
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooTemporalSession.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooTemporalSession.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooTemporalSession.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Nov 28, 2007
+ */
+package org.drools.reteoo;
+
+import org.drools.TemporalSession;
+import org.drools.common.InternalRuleBase;
+import org.drools.concurrent.ExecutorService;
+import org.drools.temporal.SessionClock;
+
+/**
+ * ReteooStatefulTemporalSession implements a temporal enabled session
+ * for Reteoo rulebases
+ * 
+ * @author etirelli
+ */
+public class ReteooTemporalSession<T extends SessionClock> extends ReteooStatefulSession
+    implements
+    TemporalSession<T> {
+
+    private static final long serialVersionUID = -2129661675928809928L;
+    
+    private T sessionClock;
+
+    public ReteooTemporalSession(int id,
+                                         InternalRuleBase ruleBase,
+                                         ExecutorService executorService,
+                                         T clock) {
+        super( id,
+               ruleBase,
+               executorService );
+        this.sessionClock = clock;
+        //Set<Observer> clockObservers = ruleBase.getClockObservers();
+		//for (Observer myObserver : clockObservers)
+        //	clock.addObserver(myObserver);
+    }
+
+    public T getSessionClock() {
+        return this.sessionClock;
+    }
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooWorkingMemory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooWorkingMemory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/ReteooWorkingMemory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,191 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
+import org.drools.FactException;
+import org.drools.FactHandle;
+import org.drools.QueryResults;
+import org.drools.base.DroolsQuery;
+import org.drools.common.AbstractWorkingMemory;
+import org.drools.common.DefaultAgenda;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalRuleBase;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.common.WorkingMemoryAction;
+import org.drools.event.RuleBaseEventListener;
+import org.drools.rule.EntryPoint;
+import org.drools.rule.Query;
+import org.drools.rule.Rule;
+import org.drools.spi.Activation;
+import org.drools.spi.PropagationContext;
+
+/**
+ * Implementation of <code>WorkingMemory</code>.
+ * 
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter </a>
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris</a>
+ */
+public class ReteooWorkingMemory extends AbstractWorkingMemory {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    /**
+     * Construct.
+     * 
+     * @param ruleBase
+     *            The backing rule-base.
+     */
+    public ReteooWorkingMemory(final int id,
+                               final InternalRuleBase ruleBase) {
+        super( id,
+               ruleBase,
+               ruleBase.newFactHandleFactory() );
+        this.agenda = new DefaultAgenda( this );
+    }
+
+    public void doInsert(final InternalFactHandle handle,
+                               final Object object,
+                               final PropagationContext propagationContext) throws FactException {
+        this.ruleBase.assertObject( handle,
+                                    object,
+                                    propagationContext,
+                                    this );
+    }
+
+    public void doRetract(final InternalFactHandle handle,
+                          final PropagationContext propagationContext) {
+        this.ruleBase.retractObject( handle,
+                                     propagationContext,
+                                     this );
+    }
+
+    public QueryResults getQueryResults(final String query) {
+        return getQueryResults( query, null );
+    }
+    
+    public QueryResults getQueryResults(final String query, final Object[] arguments) {
+
+        Object object = new DroolsQuery( query, arguments );
+        InternalFactHandle handle = this.handleFactory.newFactHandle( object, false, this );
+        
+        insert( EntryPoint.DEFAULT, // query dummy objects always use default entry point
+                handle,
+                object,
+                null,
+                null );
+        
+        final QueryTerminalNode node = (QueryTerminalNode) this.queryResults.remove( query );
+        Query queryObj = null;
+        List list = null;
+
+        if ( node == null ) {
+            // There are no results, first check the query object actually exists
+            final org.drools.rule.Package[] pkgs = this.ruleBase.getPackages();
+            for ( int i = 0; i < pkgs.length; i++ ) {
+                final Rule rule = pkgs[i].getRule( query );
+                if ( (rule != null) && (rule instanceof Query) ) {
+                    queryObj = (Query) rule;
+                    break;
+                }
+            }
+
+            this.handleFactory.destroyFactHandle( handle );
+            
+            if ( queryObj == null ) {
+                throw new IllegalArgumentException( "Query '" + query + "' does not exist" );
+            }
+            list = Collections.EMPTY_LIST;
+        } else {
+            list = (List) this.getNodeMemory( node );
+            
+            if ( list == null ) {
+                list = Collections.EMPTY_LIST;
+            } else {
+                this.clearNodeMemory( node );
+            }
+            queryObj = (Query) node.getRule();
+            
+            this.handleFactory.destroyFactHandle( handle );
+        }
+        
+        
+        
+
+        return new QueryResults( list,
+                                 queryObj,
+                                 this );
+    }
+
+    void setQueryResults(final String query,
+                         final QueryTerminalNode node) {
+        if ( this.queryResults == Collections.EMPTY_MAP ) {
+            this.queryResults = new HashMap();
+        }
+        this.queryResults.put( query,
+                               node );
+    }
+
+    public static class WorkingMemoryReteAssertAction
+        implements
+        WorkingMemoryAction {
+        private InternalFactHandle factHandle;
+
+        private boolean            removeLogical;
+
+        private boolean            updateEqualsMap;
+
+        private Rule               ruleOrigin;
+
+        private Activation         activationOrigin;
+
+        public WorkingMemoryReteAssertAction(final InternalFactHandle factHandle,
+                                             final boolean removeLogical,
+                                             final boolean updateEqualsMap,
+                                             final Rule ruleOrigin,
+                                             final Activation activationOrigin) {
+            super();
+            this.factHandle = factHandle;
+            this.removeLogical = removeLogical;
+            this.updateEqualsMap = updateEqualsMap;
+            this.ruleOrigin = ruleOrigin;
+            this.activationOrigin = activationOrigin;
+        }
+
+        public void execute(InternalWorkingMemory workingMemory) {
+
+            final PropagationContext context = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
+                                                                           PropagationContext.ASSERTION,
+                                                                           this.ruleOrigin,
+                                                                           this.activationOrigin );
+            ReteooRuleBase ruleBase = ( ReteooRuleBase ) workingMemory.getRuleBase();
+            ruleBase.assertObject( this.factHandle,
+                                                            this.factHandle.getObject(),
+                                                            context,
+                                                            workingMemory );
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/RightInputAdapterNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/RightInputAdapterNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/RightInputAdapterNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,227 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.RuleBaseConfiguration;
+import org.drools.common.BaseNode;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.NodeMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.spi.PropagationContext;
+import org.drools.util.Iterator;
+import org.drools.util.ObjectHashMap;
+import org.drools.util.ObjectHashMap.ObjectEntry;
+
+/**
+ * When joining a subnetwork into the main network again, RightInputAdapterNode adapts the 
+ * subnetwork's tuple into a fact in order right join it with the tuple being propagated in
+ * the main network.
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ * @author <a href="mailto:etirelli at redhat.com">Edson Tirelli</a>
+ *
+ */
+public class RightInputAdapterNode extends ObjectSource
+    implements
+    TupleSinkNode,
+    NodeMemory {
+
+    private static final long serialVersionUID = 400L;
+
+    private final TupleSource tupleSource;
+    
+    protected boolean          tupleMemoryEnabled;      
+
+    private TupleSinkNode       previousTupleSinkNode;
+    private TupleSinkNode       nextTupleSinkNode;
+
+    /**
+     * Constructor specifying the unique id of the node in the Rete network, the position of the propagating <code>FactHandleImpl</code> in
+     * <code>ReteTuple</code> and the source that propagates the receive <code>ReteTuple<code>s.
+     * 
+     * @param id
+     *      Unique id 
+     * @param source
+     *      The <code>TupleSource</code> which propagates the received <code>ReteTuple</code>
+     */
+    public RightInputAdapterNode(final int id,
+                                 final TupleSource source,
+                                 final BuildContext context) {
+        super( id );
+        this.tupleSource = source;
+        this.tupleMemoryEnabled = context.isTupleMemoryEnabled();
+    }
+
+    /**
+     * Creates and return the node memory
+     */
+    public Object createMemory(final RuleBaseConfiguration config) {
+        return new ObjectHashMap();
+    }
+
+    /**
+     * Takes the asserted <code>ReteTuple</code> received from the <code>TupleSource</code> and 
+     * adapts it into a FactHandleImpl
+     * 
+     * @param tuple
+     *            The asserted <code>ReteTuple</code>.
+     * @param context
+     *             The <code>PropagationContext</code> of the <code>WorkingMemory<code> action.           
+     * @param workingMemory
+     *            the <code>WorkingMemory</code> session.
+     */
+    public void assertTuple(final ReteTuple tuple,
+                            final PropagationContext context,
+                            final InternalWorkingMemory workingMemory) {
+
+        // creating a dummy fact handle to wrap the tuple
+        // final InternalFactHandle handle = workingMemory.getFactHandleFactory().newFactHandle( tuple, false, workingMemory );
+        //final InternalFactHandle handle = workingMemory.getFactHandleFactory().newFactHandle( tuple, tuple.containsEvents(), workingMemory );
+    	final InternalFactHandle handle;
+    	if (tuple.containsEvents())
+    		handle = workingMemory.getFactHandleFactory().newFactHandle( tuple, true, tuple.getCreationTimeFirstContributingEvent(), workingMemory);
+    		else handle = workingMemory.getFactHandleFactory().newFactHandle( tuple, false, workingMemory );
+    	
+        if ( this.tupleMemoryEnabled ) {
+            final ObjectHashMap memory = (ObjectHashMap) workingMemory.getNodeMemory( this );
+            // add it to a memory mapping
+            memory.put( tuple,
+                        handle );
+        }
+
+        // propagate it
+        this.sink.propagateAssertObject( handle,
+                                         context,
+                                         workingMemory );
+    }
+
+    /**
+     * Retracts the corresponding tuple by retrieving and retracting
+     * the fact created for it
+     */
+    public void retractTuple(final ReteTuple tuple,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+
+        final ObjectHashMap memory = (ObjectHashMap) workingMemory.getNodeMemory( this );
+
+        // retrieve handle from memory
+        final InternalFactHandle handle = (InternalFactHandle) memory.remove( tuple );
+
+        // propagate a retract for it
+        this.sink.propagateRetractObject( handle,
+                                          context,
+                                          workingMemory,
+                                          true );
+
+        // destroy dummy handle
+        workingMemory.getFactHandleFactory().destroyFactHandle( handle );
+    }
+
+    public void attach() {
+        this.tupleSource.addTupleSink( this );
+    }
+
+    public void attach(final InternalWorkingMemory[] workingMemories) {
+        attach();
+
+        for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+            final InternalWorkingMemory workingMemory = workingMemories[i];
+            final PropagationContext propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
+                                                                                      PropagationContext.RULE_ADDITION,
+                                                                                      null,
+                                                                                      null );
+            this.tupleSource.updateSink( this,
+                                         propagationContext,
+                                         workingMemory );
+        }
+    }
+
+    public void updateSink(final ObjectSink sink,
+                           final PropagationContext context,
+                           final InternalWorkingMemory workingMemory) {
+
+        final ObjectHashMap memory = (ObjectHashMap) workingMemory.getNodeMemory( this );
+
+        final Iterator it = memory.iterator();
+
+        // iterates over all propagated handles and assert them to the new sink
+        for ( ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next() ) {
+            sink.assertObject( (InternalFactHandle) entry.getValue(),
+                               context,
+                               workingMemory );
+        }
+    }
+
+    public void remove(ReteooBuilder builder,
+                       final BaseNode node, final InternalWorkingMemory[] workingMemories) {
+        if ( !node.isInUse() ) {
+            removeObjectSink( (ObjectSink) node );
+        }
+        removeShare(builder);
+        this.tupleSource.remove( builder,
+                                 this, workingMemories );
+    }
+    
+    public boolean isTupleMemoryEnabled() {
+        return tupleMemoryEnabled;
+    }
+
+    public void setTupleMemoryEnabled(boolean tupleMemoryEnabled) {
+        this.tupleMemoryEnabled = tupleMemoryEnabled;
+    }
+
+    /**
+     * Returns the next node
+     * @return
+     *      The next TupleSinkNode
+     */
+    public TupleSinkNode getNextTupleSinkNode() {
+        return this.nextTupleSinkNode;
+    }
+
+    /**
+     * Sets the next node 
+     * @param next
+     *      The next TupleSinkNode
+     */
+    public void setNextTupleSinkNode(final TupleSinkNode next) {
+        this.nextTupleSinkNode = next;
+    }
+
+    /**
+     * Returns the previous node
+     * @return
+     *      The previous TupleSinkNode
+     */
+    public TupleSinkNode getPreviousTupleSinkNode() {
+        return this.previousTupleSinkNode;
+    }
+
+    /**
+     * Sets the previous node 
+     * @param previous
+     *      The previous TupleSinkNode
+     */
+    public void setPreviousTupleSinkNode(final TupleSinkNode previous) {
+        this.previousTupleSinkNode = previous;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/RuleTerminalNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/RuleTerminalNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/RuleTerminalNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,580 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.drools.common.EventSupport;
+import org.drools.RuleBaseConfiguration;
+import org.drools.common.BinaryHeapQueueAgendaGroup;
+import org.drools.common.AgendaItem;
+import org.drools.common.BaseNode;
+import org.drools.common.InternalAgenda;
+import org.drools.common.InternalAgendaGroup;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalRuleFlowGroup;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.LogicalDependency;
+import org.drools.common.NodeMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.common.ScheduledAgendaItem;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.GroupElement;
+import org.drools.rule.Rule;
+import org.drools.spi.Activation;
+import org.drools.spi.ActivationGroup;
+import org.drools.spi.AgendaGroup;
+import org.drools.spi.Duration;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.RuleFlowGroup;
+import org.drools.util.Iterator;
+import org.drools.util.LinkedList;
+import org.drools.util.TupleHashTable;
+
+/**
+ * Leaf Rete-OO node responsible for enacting <code>Action</code> s on a
+ * matched <code>Rule</code>.
+ *
+ * @see org.drools.rule.Rule
+ *
+ * @author <a href="mailto:bob at eng.werken.com">bob mcwhirter </a>
+ */
+public final class RuleTerminalNode extends BaseNode
+    implements
+    TupleSinkNode,
+    NodeMemory,
+    TerminalNode {
+    // ------------------------------------------------------------
+    // Instance members
+    // ------------------------------------------------------------
+
+    private int sequence;
+
+    /**
+     *
+     */
+    private static final long  serialVersionUID = 400L;
+    /** The rule to invoke upon match. */
+    private final Rule         rule;
+    /**
+     * the subrule reference is needed to resolve declarations
+     * because declarations may have different offsets in each subrule
+     */
+    private final GroupElement subrule;
+    private final TupleSource  tupleSource;
+
+    private TupleSinkNode      previousTupleSinkNode;
+    private TupleSinkNode      nextTupleSinkNode;
+
+    protected boolean          tupleMemoryEnabled;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    /**
+     * Construct.
+     *
+     * @param inputSource
+     *            The parent tuple source.
+     * @param rule
+     *            The rule.
+     */
+    public RuleTerminalNode(final int id,
+                            final TupleSource source,
+                            final Rule rule,
+                            final GroupElement subrule,
+                            final BuildContext buildContext) {
+        super( id );
+        this.rule = rule;
+        this.tupleSource = source;
+        this.subrule = subrule;
+        this.tupleMemoryEnabled = buildContext.isTerminalNodeMemoryEnabled();
+    }
+
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+
+    /**
+     * Retrieve the <code>Action</code> associated with this node.
+     *
+     * @return The <code>Action</code> associated with this node.
+     */
+    public Rule getRule() {
+        return this.rule;
+    }
+
+    public void setSequence(int seq) {
+        this.sequence = seq;
+    }
+
+    public int getSequence() {
+        return this.sequence;
+    }
+
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // org.drools.impl.TupleSink
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+    public void assertTuple(final ReteTuple tuple,
+                            final PropagationContext context,
+                            final InternalWorkingMemory workingMemory) {
+        assertTuple( tuple,
+                     context,
+                     workingMemory,
+                     true );
+
+    }
+
+    /**
+     * Assert a new <code>Tuple</code>.
+     *
+     * @param tuple
+     *            The <code>Tuple</code> being asserted.
+     * @param workingMemory
+     *            The working memory seesion.
+     * @throws AssertionException
+     *             If an error occurs while asserting.
+     */
+    public void assertTuple(final ReteTuple tuple,
+                            final PropagationContext context,
+                            final InternalWorkingMemory workingMemory,
+                            final boolean fireActivationCreated) {
+
+        //check if the rule is effective
+        if ( !this.rule.isEffective(workingMemory.getTimeMachine()) ) {
+            return;
+        }
+
+        // if the current Rule is no-loop and the origin rule is the same and its the same set of facts (tuple) then return
+        if ( context.getType() == PropagationContext.MODIFICATION ) {
+            if ( this.rule.isNoLoop() && this.rule.equals( context.getRuleOrigin() ) && context.getActivationOrigin().getTuple().equals( tuple ) ) {
+                return;
+            }
+        } else if ( this.rule.isNoLoop() && this.rule.equals( context.getRuleOrigin() ) ) {
+            return;
+        }
+
+        //we only have to clone the head fact to make sure the graph is not affected during consequence reads after a modify
+        final ReteTuple cloned = new ReteTuple( tuple );
+
+        final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+        final Duration dur = this.rule.getDuration();
+
+        if ( dur != null && dur.getDuration( tuple ) > 0 ) {
+            final ScheduledAgendaItem item = new ScheduledAgendaItem( context.getPropagationNumber(),
+                                                                      cloned,
+                                                                      agenda,
+                                                                      context,
+                                                                      this.rule,
+                                                                      this.subrule );
+            final TerminalNodeMemory memory = (TerminalNodeMemory) workingMemory.getNodeMemory( this );
+            if ( this.rule.getActivationGroup() != null ) {
+                // Lazy cache activationGroup
+                if ( memory.getActivationGroup() == null ) {
+                    memory.setActivationGroup( workingMemory.getAgenda().getActivationGroup( this.rule.getActivationGroup() ) );
+                }
+                memory.getActivationGroup().addActivation( item );
+            }
+
+            agenda.scheduleItem( item );
+            tuple.setActivation( item );
+
+            if ( this.tupleMemoryEnabled ) {
+                memory.getTupleMemory().add( tuple );
+            }
+
+            item.setActivated( true );
+            ((EventSupport) workingMemory).getAgendaEventSupport().fireActivationCreated( item,
+                                                                         workingMemory );
+        } else {
+            // -----------------
+            // Lazy instantiation and addition to the Agenda of AgendGroup
+            // implementations
+            // ----------------
+            final TerminalNodeMemory memory = (TerminalNodeMemory) workingMemory.getNodeMemory( this );
+            InternalAgendaGroup agendaGroup = memory.getAgendaGroup();
+            if ( agendaGroup == null ) {
+                // @todo: this logic really should be encapsulated inside the Agenda
+                if ( this.rule.getAgendaGroup() == null || this.rule.getAgendaGroup().equals( "" ) || this.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) agenda.getAgendaGroup( AgendaGroup.MAIN );
+                } else {
+                    // AgendaGroup is defined, so try and get the AgendaGroup
+                    // from the Agenda
+                    agendaGroup = (InternalAgendaGroup) agenda.getAgendaGroup( this.rule.getAgendaGroup() );
+                }
+
+                memory.setAgendaGroup( agendaGroup );
+            }
+
+            // set the focus if rule autoFocus is true
+            if ( this.rule.getAutoFocus() ) {
+                agenda.setFocus( agendaGroup );
+            }
+
+            final AgendaItem item = new AgendaItem( context.getPropagationNumber(),
+                                                    cloned,
+                                                    rule.getSalience().getValue( tuple, workingMemory ),
+                                                    context,
+                                                    this.rule,
+                                                    this.subrule );
+
+            if ( this.tupleMemoryEnabled ) {
+                item.setSequenence( this.sequence );
+            }
+
+            if ( this.rule.getActivationGroup() != null ) {
+                // Lazy cache activationGroup
+                if ( memory.getActivationGroup() == null ) {
+                    memory.setActivationGroup( workingMemory.getAgenda().getActivationGroup( this.rule.getActivationGroup() ) );
+                }
+                memory.getActivationGroup().addActivation( item );
+            }
+
+            item.setAgendaGroup( agendaGroup );
+            if ( this.rule.getRuleFlowGroup() == null ) {
+                // No RuleFlowNode so add  it directly to  the Agenda
+
+                // do not add the activation if the rule is "lock-on-active" and the AgendaGroup is active
+                // we must check the context to determine if its a new tuple or an exist re-activated tuple as part of the retract
+                if ( context.getType() == PropagationContext.MODIFICATION ) {
+                    if ( this.rule.isLockOnActive() && agendaGroup.isActive() ) {
+                        Activation justifier = context.removeRetractedTuple( this.rule,
+                                                                             tuple );
+                        if ( justifier == null ) {
+                            // This rule is locked and active, do not allow new tuples to activate
+                            return;
+                        } else if ( this.rule.hasLogicalDependency() ) {
+                            copyLogicalDependencies( context,
+                                                     workingMemory,
+                                                     item,
+                                                     justifier );
+                        }
+                    } else if ( this.rule.hasLogicalDependency() ) {
+                        Activation justifier = context.removeRetractedTuple( this.rule,
+                                                                             tuple );
+                        copyLogicalDependencies( context,
+                                                 workingMemory,
+                                                 item,
+                                                 justifier );
+                    }
+                } else if ( this.rule.isLockOnActive() && agendaGroup.isActive() ) {
+                    return;
+                }
+
+                agendaGroup.add( item );
+            } else {
+                //There is  a RuleFlowNode so add it there, instead  of the Agenda
+                RuleFlowGroup rfg = memory.getRuleFlowGroup();
+                // Lazy cache ruleFlowGroup
+                if ( rfg == null ) {
+                    rfg = workingMemory.getAgenda().getRuleFlowGroup( this.rule.getRuleFlowGroup() );
+                    memory.setRuleFlowGroup( rfg );
+                }
+
+                // do not add the activation if the rule is "lock-on-active" and the RuleFlowGroup is active
+                // we must check the context to determine if its a new tuple or an exist re-activated tuple as part of the retract
+                if ( context.getType() == PropagationContext.MODIFICATION ) {
+                    if ( this.rule.isLockOnActive() && rfg.isActive() ) {
+                        Activation justifier = context.removeRetractedTuple( this.rule,
+                                                                             tuple );
+                        if ( justifier == null ) {
+                            // This rule is locked and active, do not allow new tuples to activate
+                            return;
+                        } else if ( this.rule.hasLogicalDependency() ) {
+                            copyLogicalDependencies( context,
+                                                     workingMemory,
+                                                     item,
+                                                     justifier );
+                        }
+                    } else if ( this.rule.hasLogicalDependency() ) {
+                        Activation justifier = context.removeRetractedTuple( this.rule,
+                                                                             tuple );
+                        copyLogicalDependencies( context,
+                                                 workingMemory,
+                                                 item,
+                                                 justifier );
+                    }
+                } else if ( this.rule.isLockOnActive() && rfg.isActive() ) {
+                    return;
+                }
+
+                ((InternalRuleFlowGroup) memory.getRuleFlowGroup()).addActivation( item );
+
+            }
+
+            tuple.setActivation( item );
+            memory.getTupleMemory().add( tuple );
+
+            item.setActivated( true );
+
+            // We only want to fire an event on a truly new Activation and not on an Activation as a result of a modify
+            if ( fireActivationCreated ) {
+            	((EventSupport) workingMemory).getAgendaEventSupport().fireActivationCreated( item,
+                                                                             workingMemory );
+            }
+        }
+
+        agenda.increaseActiveActivations();
+    }
+
+    private void copyLogicalDependencies(final PropagationContext context,
+                                         final InternalWorkingMemory workingMemory,
+                                         final AgendaItem item,
+                                         Activation justifier) {
+        if ( justifier != null ) {
+            final LinkedList list = justifier.getLogicalDependencies();
+            if ( list != null && !list.isEmpty() ) {
+                for ( LogicalDependency node = (LogicalDependency) list.getFirst(); node != null; node = (LogicalDependency) node.getNext() ) {
+                    final InternalFactHandle handle = (InternalFactHandle) node.getFactHandle();
+                    workingMemory.getTruthMaintenanceSystem().addLogicalDependency( handle,
+                                                                                    item,
+                                                                                    context,
+                                                                                    this.rule );
+                }
+            }
+        }
+    }
+
+    public void retractTuple(final ReteTuple leftTuple,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+        final TerminalNodeMemory memory = (TerminalNodeMemory) workingMemory.getNodeMemory( this );
+        final ReteTuple tuple = memory.getTupleMemory().remove( leftTuple );
+        if ( tuple == null ) {
+            // tuple should only be null if it was asserted and reached a no-loop causing it to exit early
+            // before being added to the node memory and an activation created and attached
+            return;
+        }
+
+        final Activation activation = tuple.getActivation();
+        if ( activation.getLogicalDependencies() != null && !activation.getLogicalDependencies().isEmpty() ) {
+            context.addRetractedTuple( this.rule,
+                                       activation );
+        }
+
+        if ( activation.isActivated() ) {
+            if ( context.getType() == PropagationContext.MODIFICATION ) {
+                // during a modify if we have either isLockOnActive or the activation has logical dependencies
+                // then we need to track retractions, so we know which are exising activations and which are truly new
+                if ( this.rule.isLockOnActive() ) {
+                    context.addRetractedTuple( this.rule,
+                                               activation );
+                }
+            }
+
+            activation.remove();
+
+            if ( activation.getActivationGroupNode() != null ) {
+                activation.getActivationGroupNode().getActivationGroup().removeActivation( activation );
+            }
+
+            if ( activation.getRuleFlowGroupNode() != null ) {
+                final InternalRuleFlowGroup ruleFlowGroup = activation.getRuleFlowGroupNode().getRuleFlowGroup();
+                ruleFlowGroup.removeActivation( activation );
+            }
+
+            ((EventSupport) workingMemory).getAgendaEventSupport().fireActivationCancelled( activation,
+                                                                           workingMemory );
+            ((InternalAgenda) workingMemory.getAgenda()).decreaseActiveActivations();
+        } else {
+            ((InternalAgenda) workingMemory.getAgenda()).decreaseDormantActivations();
+        }
+
+        workingMemory.removeLogicalDependencies( activation,
+                                                 context,
+                                                 this.rule );
+    }
+
+    public String toString() {
+        return "[RuleTerminalNode: rule=" + this.rule.getName() + "]";
+    }
+
+    public void ruleAttached() {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void attach() {
+        this.tupleSource.addTupleSink( this );
+    }
+
+    public void attach(final InternalWorkingMemory[] workingMemories) {
+        attach();
+
+        for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+            final InternalWorkingMemory workingMemory = workingMemories[i];
+            final PropagationContext propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
+                                                                                      PropagationContext.RULE_ADDITION,
+                                                                                      null,
+                                                                                      null );
+            this.tupleSource.updateSink( this,
+                                         propagationContext,
+                                         workingMemory );
+        }
+    }
+
+    public void remove(ReteooBuilder builder,
+                       final BaseNode node, final InternalWorkingMemory[] workingMemories) {
+        for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+            final InternalWorkingMemory workingMemory = workingMemories[i];
+
+            final TerminalNodeMemory memory = (TerminalNodeMemory) workingMemory.getNodeMemory( this );
+            final Iterator it = memory.getTupleMemory().iterator();
+            for ( ReteTuple tuple = (ReteTuple) it.next(); tuple != null; tuple = (ReteTuple) it.next() ) {
+                final Activation activation = tuple.getActivation();
+
+                if ( activation.isActivated() ) {
+                    activation.remove();
+                    ((EventSupport) workingMemory).getAgendaEventSupport().fireActivationCancelled( activation,
+                                                                                   workingMemory );
+                }
+
+                final PropagationContext propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
+                                                                                          PropagationContext.RULE_REMOVAL,
+                                                                                          null,
+                                                                                          null );
+                workingMemory.getTruthMaintenanceSystem().removeLogicalDependencies( activation,
+                                                                                     propagationContext,
+                                                                                     this.rule );
+            }
+
+            workingMemory.executeQueuedActions();
+            workingMemory.clearNodeMemory( this );
+        }
+
+        removeShare(builder);
+
+        this.tupleSource.remove( builder,
+                                 this, workingMemories );
+    }
+
+    public Object createMemory(final RuleBaseConfiguration config) {
+        return new TerminalNodeMemory();
+    }
+
+    public boolean isTupleMemoryEnabled() {
+        return tupleMemoryEnabled;
+    }
+
+    public void setTupleMemoryEnabled(boolean tupleMemoryEnabled) {
+        this.tupleMemoryEnabled = tupleMemoryEnabled;
+    }
+
+    /**
+     * Returns the next node
+     * @return
+     *      The next TupleSinkNode
+     */
+    public TupleSinkNode getNextTupleSinkNode() {
+        return this.nextTupleSinkNode;
+    }
+
+    /**
+     * Sets the next node
+     * @param next
+     *      The next TupleSinkNode
+     */
+    public void setNextTupleSinkNode(final TupleSinkNode next) {
+        this.nextTupleSinkNode = next;
+    }
+
+    /**
+     * Returns the previous node
+     * @return
+     *      The previous TupleSinkNode
+     */
+    public TupleSinkNode getPreviousTupleSinkNode() {
+        return this.previousTupleSinkNode;
+    }
+
+    /**
+     * Sets the previous node
+     * @param previous
+     *      The previous TupleSinkNode
+     */
+    public void setPreviousTupleSinkNode(final TupleSinkNode previous) {
+        this.previousTupleSinkNode = previous;
+    }
+
+    public int hashCode() {
+        return this.rule.hashCode();
+    }
+
+    public boolean equals(final Object object) {
+        if ( object == this ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof RuleTerminalNode) ) {
+            return false;
+        }
+
+        final RuleTerminalNode other = (RuleTerminalNode) object;
+        return this.rule.equals( other.rule );
+    }
+
+    class TerminalNodeMemory
+        implements
+        Serializable {
+        private static final long serialVersionUID = 400L;
+
+        private InternalAgendaGroup   agendaGroup;
+
+        private ActivationGroup   activationGroup;
+
+        private RuleFlowGroup     ruleFlowGroup;
+
+        private TupleHashTable    tupleMemory;
+
+        public TerminalNodeMemory() {
+            this.tupleMemory = new TupleHashTable();
+        }
+
+        public InternalAgendaGroup getAgendaGroup() {
+            return this.agendaGroup;
+        }
+
+        public void setAgendaGroup(final InternalAgendaGroup agendaGroup) {
+            this.agendaGroup = agendaGroup;
+        }
+
+        public ActivationGroup getActivationGroup() {
+            return this.activationGroup;
+        }
+
+        public void setActivationGroup(final ActivationGroup activationGroup) {
+            this.activationGroup = activationGroup;
+        }
+
+        public TupleHashTable getTupleMemory() {
+            return this.tupleMemory;
+        }
+
+        public RuleFlowGroup getRuleFlowGroup() {
+            return this.ruleFlowGroup;
+        }
+
+        public void setRuleFlowGroup(final RuleFlowGroup ruleFlowGroup) {
+            this.ruleFlowGroup = ruleFlowGroup;
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/SingleObjectSinkAdapter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/SingleObjectSinkAdapter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/SingleObjectSinkAdapter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,46 @@
+package org.drools.reteoo;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+
+public class SingleObjectSinkAdapter
+    implements
+    ObjectSinkPropagator {
+
+    private static final long serialVersionUID = 873985743021L;
+    
+    private ObjectSink sink;
+
+    public SingleObjectSinkAdapter(final ObjectSink sink) {
+        this.sink = sink;
+    }
+
+    public void propagateAssertObject(final InternalFactHandle handle,
+                                      final PropagationContext context,
+                                      final InternalWorkingMemory workingMemory) {
+        this.sink.assertObject( handle,
+                                context,
+                                workingMemory );
+
+    }
+
+    public void propagateRetractObject(final InternalFactHandle handle,
+                                       final PropagationContext context,
+                                       final InternalWorkingMemory workingMemory,
+                                       final boolean useHash) {
+        this.sink.retractObject( handle,
+                                 context,
+                                 workingMemory );
+
+    }
+
+    public ObjectSink[] getSinks() {
+        return new ObjectSink[]{this.sink};
+    }
+    
+    public int size() {
+        return 1;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/SingleTupleSinkAdapter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/SingleTupleSinkAdapter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/SingleTupleSinkAdapter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,75 @@
+package org.drools.reteoo;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+
+public class SingleTupleSinkAdapter
+    implements
+    TupleSinkPropagator {
+    private TupleSink sink;
+
+    public SingleTupleSinkAdapter(final TupleSink sink) {
+        this.sink = sink;
+    }
+
+    public void propagateAssertTuple(final ReteTuple tuple,
+                                     final InternalFactHandle handle,
+                                     final PropagationContext context,
+                                     final InternalWorkingMemory workingMemory) {
+        this.sink.assertTuple( new ReteTuple( tuple,
+                                              handle ),
+                               context,
+                               workingMemory );
+    }
+
+    public void propagateAssertTuple(final ReteTuple tuple,
+                                     final PropagationContext context,
+                                     final InternalWorkingMemory workingMemory) {
+        this.sink.assertTuple( new ReteTuple( tuple ),
+                               context,
+                               workingMemory );
+    }
+
+    public void propagateRetractTuple(final ReteTuple tuple,
+                                      final InternalFactHandle handle,
+                                      final PropagationContext context,
+                                      final InternalWorkingMemory workingMemory) {
+        this.sink.retractTuple( new ReteTuple( tuple,
+                                               handle ),
+                                context,
+                                workingMemory );
+    }
+
+    public void propagateRetractTuple(final ReteTuple tuple,
+                                      final PropagationContext context,
+                                      final InternalWorkingMemory workingMemory) {
+        this.sink.retractTuple( new ReteTuple( tuple ),
+                                context,
+                                workingMemory );
+    }
+
+    public void createAndPropagateAssertTuple(final InternalFactHandle handle,
+                                              final PropagationContext context,
+                                              final InternalWorkingMemory workingMemory) {
+        this.sink.assertTuple( new ReteTuple( handle ),
+                               context,
+                               workingMemory );
+    }
+
+    public void createAndPropagateRetractTuple(final InternalFactHandle handle,
+                                               final PropagationContext context,
+                                               final InternalWorkingMemory workingMemory) {
+        this.sink.retractTuple( new ReteTuple( handle ),
+                                context,
+                                workingMemory );
+    }
+
+    public TupleSink[] getSinks() {
+        return new TupleSink[]{this.sink};
+    }
+
+    public int size() {
+        return (this.sink != null) ? 1 : 0;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/Sink.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/Sink.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/Sink.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,10 @@
+package org.drools.reteoo;
+
+/**
+ * A simple markup interfaces for Sink types
+ * 
+ * @author etirelli
+ */
+interface Sink {
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TerminalNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TerminalNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TerminalNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2006 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 markup interface for terminal nodes
+ * 
+ * @author etirelli
+ */
+public interface TerminalNode {
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TimeWindowNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TimeWindowNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TimeWindowNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,992 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.reteoo;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.log4j.Logger;
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuntimeDroolsException;
+import org.drools.common.BetaConstraints;
+import org.drools.common.EventFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.TimeWindow;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.PropagationContext;
+import org.drools.temporal.AbstractSessionClock;
+import org.drools.temporal.EventExpiration;
+import org.drools.temporal.GlobalSessionClockImpl;
+import org.drools.util.ArrayUtils;
+import org.drools.util.Entry;
+import org.drools.util.FactEntry;
+import org.drools.util.Iterator;
+import org.drools.util.ObjectHashMap.ObjectEntry;
+
+/**
+ * TimeWindowNode
+ * A beta node capable of doing window functionality, i.e. filter events with regard to specific window boundaries and aggregate on some specified value.
+ *
+ * @author mgroch
+ */
+public class TimeWindowNode extends BetaNode
+	/*implements Observer*/{
+	
+	Logger myLogger = Logger.getLogger(TimeWindowNode.class.getName());
+    
+	private static final long                serialVersionUID = 400L;
+
+    private final boolean                    unwrapRightObject;
+    private final TimeWindow                 timeWindow;
+    private final AlphaNodeFieldConstraint[] resultConstraints;
+    private final BetaConstraints            resultBinder;
+    private final long						 windowSize;
+    private long						     windowStart, windowEnd;
+    private final PropagationContext         DEFAULT_RETRACTION_CONTEXT = new PropagationContextImpl(0, PropagationContext.RETRACTION, null, null);;
+    private final LinkedList<EventExpiration<?>> orderedExpirationList;
+    private Set<InternalFactHandle> eventObjectsToRetract;
+	private Set<ReteTuple> eventTuplesToRetract;
+	private final EventExpirationComparator evexComparator;
+
+    public TimeWindowNode(final int id,
+                          final TupleSource leftInput,
+                          final ObjectSource rightInput,
+                          final AlphaNodeFieldConstraint[] resultConstraints,
+                          final BetaConstraints sourceBinder,
+                          final BetaConstraints resultBinder,
+                          final TimeWindow timeWindow,
+                          final boolean unwrapRightObject,
+                          final BuildContext context) {
+        super( id,
+               leftInput,
+               rightInput,
+               sourceBinder );
+        this.resultBinder = resultBinder;
+        this.resultConstraints = resultConstraints;
+        this.timeWindow = timeWindow;
+        this.unwrapRightObject = unwrapRightObject;
+        this.tupleMemoryEnabled = context.isTupleMemoryEnabled();
+        this.windowSize = timeWindow.getWindowSize();
+        this.windowStart = 0;
+        this.windowEnd = 0;
+        this.orderedExpirationList = new LinkedList<EventExpiration<?>>();
+    	this.evexComparator = new EventExpirationComparator();
+    	this.eventObjectsToRetract = new HashSet<InternalFactHandle>();
+    	this.eventTuplesToRetract = new HashSet<ReteTuple>();
+
+    }
+    
+    // original method signature like it is invoked by original Rete when inserting a new event into wm (no modification)
+    public void assertTuple(final ReteTuple leftTuple,
+            final PropagationContext context,
+            final InternalWorkingMemory workingMemory){
+    	
+    	this.assertTuple(leftTuple, context, workingMemory, false);
+    }
+
+    /**
+     * @inheritDoc
+     * 
+     *  When a new tuple is asserted into an TimeWindowNode, do this:
+     *  
+     *  1. Select all matching objects from right memory
+     *  2. Execute the initialization code using the tuple + matching objects
+     *  3. Execute the accumulation code for each combination of tuple+object
+     *  4. Execute the return code
+     *  5. Create a new CalculatedObjectHandle for the resulting object and add it to the tuple
+     *  6. Propagate the tuple
+     *  
+     *  The initialization, accumulation and return codes, in JBRules, are assembled
+     *  into a generated method code and called once for the whole match, as you can see
+     *  bellow:
+     *  
+     *   Object result = this.timewindow.accumulate( ... );
+     *  
+     */
+    public void assertTuple(final ReteTuple leftTuple,
+                            final PropagationContext context,
+                            final InternalWorkingMemory workingMemory,
+                            final boolean isPartOfUpdate) {
+       
+        /*try {
+    	
+        	timeWindowLogger.debug ("Thread "+Thread.currentThread().getId() +": TRYING TO ENTER assertTuple("+leftTuple.getLastHandle().getObject().toString()+"); currentHoldCount: "+lock.getHoldCount());
+        	lock.lock(); timeWindowLogger.debug ("Thread "+Thread.currentThread().getId() +": ENTERING assertTuple("+leftTuple.getLastHandle().getObject().toString()+"); currentHoldCount: "+lock.getHoldCount());
+        */
+    	
+    	final TimeWindowMemory memory = (TimeWindowMemory) workingMemory.getNodeMemory( this );
+        	
+		// update window bounds according to current session clock value
+		long currentTime = GlobalSessionClockImpl.getInstance().getCurrentTime();
+		if (!isPartOfUpdate && this.updateWindowBounds(currentTime))
+			this.updateNodeMemory(currentTime, workingMemory);
+        
+        TimeWindowResult twresult = new TimeWindowResult();
+
+        //InternalFactHandle lastHandle = leftTuple.getLastHandle();
+    	boolean meetsWindowConstraints = true;
+    	long eventEnd;// = 0;
+    	
+        if ( this.tupleMemoryEnabled ) {
+        	      	
+        	if (leftTuple.containsEvents()){
+        	
+	            try {
+	    			eventEnd = leftTuple.getCreationTimeFirstContributingEvent();
+	    		} catch (ClassCastException e) {
+	    			System.err.println ("Unable to retrieve timestamp - Expected event:\n");
+	    			e.printStackTrace();
+	    			eventEnd = Long.MIN_VALUE;
+	    		}
+	            
+	    		// add tuple to time-ordered queue of tuples only if it meets window constraints
+	            if (!(windowStart <= eventEnd && eventEnd <= windowEnd))
+	            	meetsWindowConstraints = false;
+	            // add negative event only if tuple contains an event and meets window constraints
+	            else addExpiration(new EventExpiration<ReteTuple>(leftTuple, true, eventEnd+windowSize));
+
+        	}
+        	
+        	if (meetsWindowConstraints){
+        		memory.betaMemory.getTupleMemory().add( leftTuple );
+        		memory.betaMemory.getCreatedHandles().put( leftTuple,
+                                            twresult,
+                                            false );
+        	}
+        }
+
+        if (meetsWindowConstraints){
+        	
+        	//timeWindowLogger.debug("meetswindowConstraints");
+        	
+	        final Object twContext = this.timeWindow.createContext();
+	
+	        twresult.context = twContext;
+	        this.timeWindow.init( memory.workingMemoryContext,
+	                              twContext,
+	                              leftTuple,
+	                              workingMemory );
+	
+	        final Iterator it = memory.betaMemory.getFactHandleMemory().iterator( leftTuple );
+	        this.constraints.updateFromTuple( workingMemory,
+	                                          leftTuple );
+	
+	        for ( FactEntry entry = (FactEntry) it.next(); entry != null; entry = (FactEntry) it.next() ) {
+	            InternalFactHandle handle = entry.getFactHandle();
+	            if ( this.constraints.isAllowedCachedLeft( handle ) ) {
+	                if ( this.unwrapRightObject ) {
+	                    // if there is a subnetwork, handle must be unwrapped
+	                    ReteTuple tuple = (ReteTuple) handle.getObject();
+	                    handle = tuple.getLastHandle();
+	                    this.timeWindow.accumulate( memory.workingMemoryContext,
+	                                                twContext,
+	                                                tuple,
+	                                                handle,
+	                                                workingMemory );
+	                } else {
+	                    this.timeWindow.accumulate( memory.workingMemoryContext,
+	                                                twContext,
+	                                                leftTuple,
+	                                                handle,
+	                                                workingMemory );
+	                }
+	            }
+	        }
+	        
+	        this.constraints.resetTuple();
+	        
+	        //timeWindowLogger.debug("timeWindow accumulated");
+	
+	        final Object result = this.timeWindow.getResult( memory.workingMemoryContext,
+	                                                         twContext,
+	                                                         leftTuple,
+	                                                         workingMemory );
+	        
+	        if( result == null ) {
+	            throw new RuntimeDroolsException("TimeWindow must not return a null value.");
+	        }
+	
+	        // First alpha node filters
+	        boolean isAllowed = true;
+	        final InternalFactHandle handle = workingMemory.getFactHandleFactory().newFactHandle( result, false, workingMemory ); // so far, result is not an event
+	
+	        for ( int i = 0, length = this.resultConstraints.length; i < length; i++ ) {
+	            if ( !this.resultConstraints[i].isAllowed( handle,
+	                                                       workingMemory ) ) {
+	                isAllowed = false;
+	                break;
+	            }
+	        }
+	        if ( isAllowed ) {
+	            this.resultBinder.updateFromTuple( workingMemory,
+	                                               leftTuple );
+	            if ( this.resultBinder.isAllowedCachedLeft( handle ) ) {
+	                twresult.handle = handle;
+	
+	                //timeWindowLogger.debug("before propagation to sink");
+	                this.sink.propagateAssertTuple( leftTuple,
+	                                                handle,
+	                                                context,
+	                                                workingMemory );
+	                //timeWindowLogger.debug("after propagation to sink");
+	                
+	            } else {
+	                workingMemory.getFactHandleFactory().destroyFactHandle( handle );
+	            }
+	        } else {
+	            workingMemory.getFactHandleFactory().destroyFactHandle( handle );
+	        }
+        
+    	}
+    /*} finally {
+    	lock.unlock(); timeWindowLogger.debug ("Thread "+Thread.currentThread().getId() +": LEAVING assertTuple("+leftTuple.getLastHandle().getObject().toString()+"); currentHoldCount: "+lock.getHoldCount());
+    }*/
+        
+    }
+
+    /**
+     * @inheritDoc
+     * 
+     * As the TimeWindow node will always propagate the tuple,
+     * it must always also retreat it.
+     * 
+     */
+    public void retractTuple(final ReteTuple leftTuple,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+    	
+    	/*try{
+    		
+    		myLogger.debug ("Thread "+Thread.currentThread().getId() +": TRYING TO ENTER retractTuple("+leftTuple.getLastHandle().getObject().toString()+"); currentHoldCount: "+lock.getHoldCount());
+    		lock.lock(); myLogger.debug ("Thread "+Thread.currentThread().getId() +": ENTERING retractTuple("+leftTuple.getLastHandle().getObject().toString()+"); currentHoldCount: "+lock.getHoldCount());
+    	*/
+    	myLogger.debug ("Retracting "+leftTuple.toString());
+    	
+    		final TimeWindowMemory memory = (TimeWindowMemory) workingMemory.getNodeMemory( this );
+	        memory.betaMemory.getTupleMemory().remove( leftTuple );
+	        final TimeWindowResult accresult = (TimeWindowResult) memory.betaMemory.getCreatedHandles().remove( leftTuple );
+	
+	        // if tuple was propagated
+	        if ( accresult.handle != null ) {
+	            this.sink.propagateRetractTuple( leftTuple,
+	                                             accresult.handle,
+	                                             context,
+	                                             workingMemory );
+	
+	            // Destroying the acumulate result object 
+	            workingMemory.getFactHandleFactory().destroyFactHandle( accresult.handle );
+	        }
+	        
+       /* } finally {
+        	lock.unlock(); myLogger.debug ("Thread "+Thread.currentThread().getId() +": LEAVING retractTuple("+leftTuple.getLastHandle().getObject().toString()+"); currentHoldCount: "+lock.getHoldCount());
+        }*/
+    }
+    
+    /**
+     *  @inheritDoc
+     *  
+     *  If a bunch of objects is retracted, call modify tuple for each
+     *  tuple match.
+     */
+    public void retractEventTuples(Set<ReteTuple> tuples,
+                              //final PropagationContext context,
+                              final InternalWorkingMemory workingMemory) {
+    	for (ReteTuple tuple : tuples)
+    		retractTuple(tuple, DEFAULT_RETRACTION_CONTEXT, workingMemory);
+    }
+
+    /**
+     * @inheritDoc
+     * 
+     *  When a new object is asserted into an TimeWindowNode, do this:
+     *  
+     *  1. Select all matching tuples from left memory
+     *  2. For each matching tuple, call a modify tuple
+     *  
+     */
+    public void assertObject(final InternalFactHandle handle,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+
+    	/*try{
+    	
+    		myLogger.debug ("Thread "+Thread.currentThread().getId() +": TRYING TO ENTER assertObject("+handle.getObject().toString()+"); currentHoldCount: "+lock.getHoldCount());
+    		lock.lock(); myLogger.debug ("Thread "+Thread.currentThread().getId() +": ENTERING assertObject("+handle.getObject().toString()+"); currentHoldCount: "+lock.getHoldCount());
+    	*/
+    	
+    	final TimeWindowMemory memory = (TimeWindowMemory) workingMemory.getNodeMemory( this );
+    	
+		// update window bounds according to current session clock value
+    	long currentTime = GlobalSessionClockImpl.getInstance().getCurrentTime();
+		if (this.updateWindowBounds(currentTime))
+			this.updateNodeMemory(currentTime, workingMemory);
+        
+        boolean meetsWindowConstraints = true;
+        long eventEnd;
+        
+        if (handle.isEvent()){
+        	EventFactHandle evHandle;
+	        
+        	try {
+				evHandle = ((EventFactHandle)handle);
+				eventEnd = evHandle.getEndTimestamp();	
+        	} catch (ClassCastException e) {
+				System.err.println ("Unable to retrieve timestamp - Expected event:\n");
+				e.printStackTrace();
+				eventEnd = Long.MIN_VALUE;
+			}
+				// add event fact handle to time-ordered queue of events only if it meets window constraints
+		        if (!(windowStart <= eventEnd && eventEnd <= windowEnd))
+		        	meetsWindowConstraints = false;
+		        // add negative event only if object is an event and meets window constraints
+		        else addExpiration(new EventExpiration<InternalFactHandle>(handle, false, eventEnd+windowSize));
+        }
+       
+        if (meetsWindowConstraints){
+        	
+        	memory.betaMemory.getFactHandleMemory().add( handle );
+
+	        if ( ! this.tupleMemoryEnabled ) {
+	            // do nothing here, as we know there are no left tuples at this stage in sequential mode.
+	            return;
+	        }
+	
+	        this.constraints.updateFromFactHandle( workingMemory,
+	                                               handle );
+	
+	        // need to clone the tuples to avoid concurrent modification exceptions
+	        Entry[] tuples = memory.betaMemory.getTupleMemory().toArray();
+	        for ( int i = 0; i < tuples.length; i++ ) {
+	            ReteTuple tuple = (ReteTuple) tuples[i];
+	            if ( this.constraints.isAllowedCachedRight( tuple ) ) {
+	                if ( this.timeWindow.supportsReverse() || context.getType() == PropagationContext.ASSERTION ) {
+	                    modifyTuple( true,
+	                                 tuple,
+	                                 handle,
+	                                 context,
+	                                 workingMemory );
+	                } else {
+	                    // context is MODIFICATION and does not supports reverse
+	                    this.retractTuple( tuple,
+	                                       context,
+	                                       workingMemory );
+	                    this.assertTuple( tuple,
+	                                      context,
+	                                      workingMemory,
+	                                      true);
+	                }
+	            }
+	        }
+	        
+	        this.constraints.resetFactHandle();
+        }
+        
+    	/*} finally {
+    		lock.unlock(); myLogger.debug ("Thread "+Thread.currentThread().getId() +": LEAVING assertObject("+handle.getObject().toString()+"); currentHoldCount: "+lock.getHoldCount());
+    	}*/
+        
+    }
+
+    /**
+     *  @inheritDoc
+     *  
+     *  If an object is retract, call modify tuple for each
+     *  tuple match.
+     */
+    public void retractObject(final InternalFactHandle handle,
+                              final PropagationContext context,
+                              final InternalWorkingMemory workingMemory) {
+    	
+    	/*try{
+    		
+	    	myLogger.debug ("Thread "+Thread.currentThread().getId() +": TRYING TO ENTER retractObject("+handle.getObject().toString()+"); currentHoldCount: "+lock.getHoldCount());
+	    	lock.lock(); myLogger.debug ("Thread "+Thread.currentThread().getId() +": ENTERING retractObject("+handle.getObject().toString()+"); currentHoldCount: "+lock.getHoldCount());
+		   */ 	
+	    	final TimeWindowMemory memory = (TimeWindowMemory) workingMemory.getNodeMemory( this );
+	        if ( !memory.betaMemory.getFactHandleMemory().remove( handle ) ) {
+	            return;
+	        }
+	
+	        this.constraints.updateFromFactHandle( workingMemory,
+	                                               handle );
+	        // need to clone the tuples to avoid concurrent modification exceptions
+	        Entry[] tuples = memory.betaMemory.getTupleMemory().toArray();
+	        for ( int i = 0; i < tuples.length; i++ ) {
+	            ReteTuple tuple = (ReteTuple) tuples[i];
+	            if ( this.constraints.isAllowedCachedRight( tuple ) ) {
+	                if ( this.timeWindow.supportsReverse() ) {
+	                    this.modifyTuple( false,
+	                                      tuple,
+	                                      handle,
+	                                      context,
+	                                      workingMemory );
+	                } else {
+	                    this.retractTuple( tuple,
+	                                       context,
+	                                       workingMemory );
+	                    this.assertTuple( tuple,
+	                                      context,
+	                                      workingMemory,
+	                                      true);
+	                }
+	            }
+	        }
+	        
+	        this.constraints.resetFactHandle();
+        
+    	/*} finally {
+    		lock.unlock(); myLogger.debug ("Thread "+Thread.currentThread().getId() +": LEAVING retractObject("+handle.getObject().toString()+"); currentHoldCount: "+lock.getHoldCount());
+    	}*/
+    }
+    
+    /**
+     *  @inheritDoc
+     *  
+     *  If a bunch of objects is retracted, call modify tuple for each
+     *  tuple match.
+     */
+    public void retractEventObjects(Set<InternalFactHandle> handles,
+                              //final PropagationContext context,
+                              final InternalWorkingMemory workingMemory) {
+    	
+    	/*try{
+    		
+	    	myLogger.debug ("Thread "+Thread.currentThread().getId() +": TRYING TO ENTER retractEventObjects(); currentHoldCount: "+lock.getHoldCount());
+	    	lock.lock(); myLogger.debug ("Thread "+Thread.currentThread().getId() +": ENTERING retractEventObjects(); currentHoldCount: "+lock.getHoldCount());
+	    	*/
+	    	final TimeWindowMemory memory = (TimeWindowMemory) workingMemory.getNodeMemory( this );
+	       
+	    	if ( this.timeWindow.supportsReverse() ) {
+	    		
+	    		Map<ReteTuple,Set<InternalFactHandle>> tuplesMap = new HashMap<ReteTuple,Set<InternalFactHandle>>();
+	    		
+	    		for (InternalFactHandle currHandle : handles){
+	    	    	
+	    	    	if ( !memory.betaMemory.getFactHandleMemory().remove( currHandle ) ) {
+	    	            return;
+	    	        }
+	    	        
+	    	        this.constraints.updateFromFactHandle( workingMemory,
+	    	                                               currHandle );
+	    	        
+	    	        // need to clone the tuples to avoid concurrent modification exceptions
+	    	        Entry[] tuples = memory.betaMemory.getTupleMemory().toArray();
+	    	        for ( int i = 0; i < tuples.length; i++ ) {
+	    	            ReteTuple tuple = (ReteTuple) tuples[i];
+	    	            if ( this.constraints.isAllowedCachedRight( tuple ) ){
+	    	            	if (!tuplesMap.containsKey(tuple))
+	    	            		tuplesMap.put(tuple, new HashSet<InternalFactHandle>());
+	    	            	tuplesMap.get(tuple).add(currHandle);
+	    	            }
+	    	        }
+	    	        
+	    	        this.constraints.resetFactHandle();
+	        	
+	        	}
+	    		
+	    		for (ReteTuple tupleToModify : tuplesMap.keySet())
+	    			this.modifyEventTuple( false,
+	                    tupleToModify,
+	                    tuplesMap.get(tupleToModify),
+	                    DEFAULT_RETRACTION_CONTEXT, //context,
+	                    workingMemory );
+	    		
+	    	} else {
+	    		
+	    		Set<ReteTuple> tuplesSet = new HashSet<ReteTuple>();
+	    		
+	    		for (InternalFactHandle currHandle : handles){
+	    	    	
+	    	    	if ( !memory.betaMemory.getFactHandleMemory().remove( currHandle ) ) {
+	    	            return;
+	    	        }
+	    	        
+	    	        this.constraints.updateFromFactHandle( workingMemory,
+	    	                                               currHandle );
+	    	        
+	    	        // need to clone the tuples to avoid concurrent modification exceptions
+	    	        Entry[] tuples = memory.betaMemory.getTupleMemory().toArray();
+	    	        for ( int i = 0; i < tuples.length; i++ ) {
+	    	            ReteTuple tuple = (ReteTuple) tuples[i];
+	    	            if ( this.constraints.isAllowedCachedRight( tuple ) )
+	    	            	tuplesSet.add(tuple);
+	    	        }
+	    	        
+	    	        this.constraints.resetFactHandle();
+	        	
+	        	}
+	    		
+	    		for (ReteTuple tupleToModify : tuplesSet)
+	    		 {
+	                 this.retractTuple( tupleToModify,
+	                		 			DEFAULT_RETRACTION_CONTEXT, //context,
+	                                    workingMemory );
+	                 this.assertTuple( tupleToModify,
+	                		 		   DEFAULT_RETRACTION_CONTEXT, //context,
+	                                   workingMemory,
+	                                   true);
+	         }
+	    	
+	    	}
+    	
+    	/*} finally {
+    		lock.unlock(); myLogger.debug ("Thread "+Thread.currentThread().getId() +": LEAVING retractObjects(); currentHoldCount: "+lock.getHoldCount());
+    	}*/
+    	
+    }
+    
+    public void modifyEventTuple(final boolean isAssert,
+            final ReteTuple leftTuple,
+            Set<InternalFactHandle> handles,
+            final PropagationContext context,
+            final InternalWorkingMemory workingMemory) {
+
+    	/*try{
+    		
+	    	myLogger.debug ("Thread "+Thread.currentThread().getId() +": TRYING TO ENTER modifyTuple_setOfHandles(); currentHoldCount: "+lock.getHoldCount());
+	    	lock.lock(); myLogger.debug ("Thread "+Thread.currentThread().getId() +": ENTERING modifyTuple_setOfHandles(); currentHoldCount: "+lock.getHoldCount());
+    	*/
+			final TimeWindowMemory memory = (TimeWindowMemory) workingMemory.getNodeMemory( this );
+			TimeWindowResult accresult = (TimeWindowResult) memory.betaMemory.getCreatedHandles().get( leftTuple );
+			
+			//myLogger.debug("accresult initialized");
+			
+			// if tuple was propagated
+			if ( accresult.handle != null ) {
+				this.sink.propagateRetractTuple( leftTuple,
+				                             accresult.handle,
+				                             context,
+				                             workingMemory );
+				
+				// Destroying the acumulate result object 
+				workingMemory.getFactHandleFactory().destroyFactHandle( accresult.handle );
+				accresult.handle = null;
+			}
+			
+			//myLogger.debug("accresult.handle != null and its retraction propagated");
+			
+			if ( context.getType() == PropagationContext.ASSERTION && accresult.context == null ) {
+					final Object accContext = this.timeWindow.createContext();
+					
+					this.timeWindow.init( memory.workingMemoryContext,
+					                      accContext,
+					                      leftTuple,
+					                      workingMemory );
+					
+					accresult.context = accContext;
+				}
+			
+			//myLogger.debug("if accContext == ASSERTION new accContext would have been created and timewindow would hve been initialzed");
+			
+			for (InternalFactHandle handle : handles){
+			
+				ReteTuple tuple = leftTuple;
+				if ( this.unwrapRightObject ) {
+					// if there is a subnetwork, handle must be unwrapped
+					myLogger.debug ("SUBNETWORK_multiple");
+					tuple = (ReteTuple) handle.getObject();
+					handle = tuple.getLastHandle();
+				}
+				
+				if ( context.getType() == PropagationContext.ASSERTION ) {
+					/*
+					// assertion
+					if ( accresult.context == null ) {
+						final Object accContext = this.timeWindow.createContext();
+						
+						this.timeWindow.init( memory.workingMemoryContext,
+						                      accContext,
+						                      leftTuple,
+						                      workingMemory );
+						
+						accresult.context = accContext;
+					}*/
+	
+					myLogger.debug ("ASSERTION_multiple");
+					this.timeWindow.accumulate( memory.workingMemoryContext,
+					                        accresult.context,
+					                        tuple,
+					                        handle,
+					                        workingMemory );
+				} else if ( context.getType() == PropagationContext.MODIFICATION || 
+				context.getType() == PropagationContext.RULE_ADDITION || 
+				context.getType() == PropagationContext.RULE_REMOVAL ) {
+					// modification
+					myLogger.debug ("MODIFICATION_multiple");
+					if ( isAssert ) {
+						this.timeWindow.accumulate( memory.workingMemoryContext,
+						                            accresult.context,
+						                            tuple,
+						                            handle,
+						                            workingMemory );
+					} else {
+						this.timeWindow.reverse( memory.workingMemoryContext,
+						                         accresult.context,
+						                         tuple,
+						                         handle,
+						                         workingMemory );
+					}
+				} else {
+					// retraction
+					myLogger.debug ("RETRACTION_multiple");
+					this.timeWindow.reverse( memory.workingMemoryContext,
+					                     accresult.context,
+					                     tuple,
+					                     handle,
+					                     workingMemory );
+				}
+			
+			}
+			
+			//myLogger.debug("modification finished and ready to retrieve the accResult");
+			
+			final Object result = this.timeWindow.getResult( memory.workingMemoryContext,
+			                                         accresult.context,
+			                                         leftTuple,
+			                                         workingMemory );
+			
+			if( result == null ) {
+				throw new RuntimeDroolsException("TimeWindow must not return a null value.");
+			}
+			
+			// First alpha node filters
+			boolean isAllowed = true;
+			final InternalFactHandle createdHandle = workingMemory.getFactHandleFactory().newFactHandle( result, false, workingMemory ); // so far, result is not an event
+			for ( int i = 0, length = this.resultConstraints.length; i < length; i++ ) {
+				if ( !this.resultConstraints[i].isAllowed( createdHandle,
+				                                       workingMemory ) ) {
+					isAllowed = false;
+					break;
+				}
+			}
+			//myLogger.debug("alpha node filtering done");
+			if ( isAllowed ) {
+				this.resultBinder.updateFromTuple( workingMemory,
+				                               leftTuple );
+				if ( this.resultBinder.isAllowedCachedLeft( createdHandle ) ) {
+					accresult.handle = createdHandle;
+					
+					//myLogger.debug("before propagating left tuple");
+					this.sink.propagateAssertTuple( leftTuple,
+					                                createdHandle,
+					                                context,
+					                                workingMemory );
+					//myLogger.debug("after propagating left tuple");
+				} else {
+					workingMemory.getFactHandleFactory().destroyFactHandle( createdHandle );
+				}
+			
+				this.resultBinder.resetTuple();
+			} else {
+				workingMemory.getFactHandleFactory().destroyFactHandle( createdHandle );
+			}
+			//myLogger.debug("resultbinder udated and propagated");
+		
+    	/*} finally {
+    		lock.unlock(); myLogger.debug ("Thread "+Thread.currentThread().getId() +": LEAVING modifyTuple_setOfHandles(); currentHoldCount: "+lock.getHoldCount());
+    	}*/
+	} 
+
+    public void modifyTuple(final boolean isAssert,
+                            final ReteTuple leftTuple,
+                            InternalFactHandle handle,
+                            final PropagationContext context,
+                            final InternalWorkingMemory workingMemory) {
+
+    	/*try{
+    		
+	    	myLogger.debug ("Thread "+Thread.currentThread().getId() +": TRYING TO ENTER modifyTuple_singleHandle(); currentHoldCount: "+lock.getHoldCount());
+	    	lock.lock(); myLogger.debug ("Thread "+Thread.currentThread().getId() +": ENTERING modifyTuple_singleHandle(); currentHoldCount: "+lock.getHoldCount());
+
+*/	        final TimeWindowMemory memory = (TimeWindowMemory) workingMemory.getNodeMemory( this );
+	        TimeWindowResult accresult = (TimeWindowResult) memory.betaMemory.getCreatedHandles().get( leftTuple );
+	
+	        // if tuple was propagated
+	        if ( accresult.handle != null ) {
+	            this.sink.propagateRetractTuple( leftTuple,
+	                                             accresult.handle,
+	                                             context,
+	                                             workingMemory );
+	
+	            // Destroying the acumulate result object 
+	            workingMemory.getFactHandleFactory().destroyFactHandle( accresult.handle );
+	            accresult.handle = null;
+	        }
+	
+	        ReteTuple tuple = leftTuple;
+	        if ( this.unwrapRightObject ) {
+	            // if there is a subnetwork, handle must be unwrapped
+	        	myLogger.debug ("SUBNETWORK");
+	            tuple = (ReteTuple) handle.getObject();
+	            handle = tuple.getLastHandle();
+	        }
+	
+	        if ( context.getType() == PropagationContext.ASSERTION ) {
+	            // assertion
+	        	myLogger.debug ("ASSERTION");
+	            if ( accresult.context == null ) {
+	                final Object accContext = this.timeWindow.createContext();
+	
+	                this.timeWindow.init( memory.workingMemoryContext,
+	                                      accContext,
+	                                      leftTuple,
+	                                      workingMemory );
+	
+	                accresult.context = accContext;
+	            }
+	
+	            this.timeWindow.accumulate( memory.workingMemoryContext,
+	                                        accresult.context,
+	                                        tuple,
+	                                        handle,
+	                                        workingMemory );
+	        } else if ( context.getType() == PropagationContext.MODIFICATION || 
+	                context.getType() == PropagationContext.RULE_ADDITION || 
+	                context.getType() == PropagationContext.RULE_REMOVAL ) {
+	            // modification
+	        	myLogger.debug ("MODIFICATION");
+	            if ( isAssert ) {
+	                this.timeWindow.accumulate( memory.workingMemoryContext,
+	                                            accresult.context,
+	                                            tuple,
+	                                            handle,
+	                                            workingMemory );
+	            } else {
+	                this.timeWindow.reverse( memory.workingMemoryContext,
+	                                         accresult.context,
+	                                         tuple,
+	                                         handle,
+	                                         workingMemory );
+	            }
+	        } else {
+	            // retraction
+	        	myLogger.debug ("RETRACTION");
+	            this.timeWindow.reverse( memory.workingMemoryContext,
+	                                     accresult.context,
+	                                     tuple,
+	                                     handle,
+	                                     workingMemory );
+	        }
+	
+	        final Object result = this.timeWindow.getResult( memory.workingMemoryContext,
+	                                                         accresult.context,
+	                                                         leftTuple,
+	                                                         workingMemory );
+	
+	        if( result == null ) {
+	            throw new RuntimeDroolsException("TimeWindow must not return a null value.");
+	        }
+	
+	        // First alpha node filters
+	        boolean isAllowed = true;
+	        final InternalFactHandle createdHandle = workingMemory.getFactHandleFactory().newFactHandle( result, false, workingMemory ); // so far, result is not an event
+	        for ( int i = 0, length = this.resultConstraints.length; i < length; i++ ) {
+	            if ( !this.resultConstraints[i].isAllowed( createdHandle,
+	                                                       workingMemory ) ) {
+	                isAllowed = false;
+	                break;
+	            }
+	        }
+	        if ( isAllowed ) {
+	            this.resultBinder.updateFromTuple( workingMemory,
+	                                               leftTuple );
+	            if ( this.resultBinder.isAllowedCachedLeft( createdHandle ) ) {
+	                accresult.handle = createdHandle;
+	
+	                this.sink.propagateAssertTuple( leftTuple,
+	                                                createdHandle,
+	                                                context,
+	                                                workingMemory );
+	            } else {
+	                workingMemory.getFactHandleFactory().destroyFactHandle( createdHandle );
+	            }
+	            
+	            this.resultBinder.resetTuple();
+	        } else {
+	            workingMemory.getFactHandleFactory().destroyFactHandle( createdHandle );
+	        }
+        
+    	/*} finally {
+    		lock.unlock(); myLogger.debug ("Thread "+Thread.currentThread().getId() +": LEAVING modifyTuple_singleHandle(); currentHoldCount: "+lock.getHoldCount());
+    	}*/
+    }
+
+    public void updateSink(final TupleSink sink,
+                           final PropagationContext context,
+                           final InternalWorkingMemory workingMemory) {
+
+    	/*try{
+    		
+	    	myLogger.debug ("Thread "+Thread.currentThread().getId() +": TRYING TO ENTER updateSink(); currentHoldCount: "+lock.getHoldCount());
+	    	lock.lock(); myLogger.debug ("Thread "+Thread.currentThread().getId() +": ENTERING updateSink(); currentHoldCount: "+lock.getHoldCount());
+    	*/
+	    	final TimeWindowMemory memory = (TimeWindowMemory) workingMemory.getNodeMemory( this );
+	
+	        final Iterator it = memory.betaMemory.getCreatedHandles().iterator();
+	
+	        for ( ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next() ) {
+	            TimeWindowResult accresult = (TimeWindowResult) entry.getValue();
+	            sink.assertTuple( new ReteTuple( (ReteTuple) entry.getKey(),
+	                                             accresult.handle ),
+	                              context,
+	                              workingMemory );
+	        }
+        
+    	/*} finally {
+    		lock.unlock(); myLogger.debug ("Thread "+Thread.currentThread().getId() +": LEAVING updateSink(); currentHoldCount: "+lock.getHoldCount());
+    	}*/
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.BaseNode#hashCode()
+     */
+    public int hashCode() {
+        return this.leftInput.hashCode() ^ this.rightInput.hashCode() ^ this.timeWindow.hashCode() ^ this.resultBinder.hashCode() ^ ArrayUtils.hashCode( this.resultConstraints );
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof TimeWindowNode) ) {
+            return false;
+        }
+
+        final TimeWindowNode other = (TimeWindowNode) object;
+
+        if ( this.getClass() != other.getClass() || (!this.leftInput.equals( other.leftInput )) || (!this.rightInput.equals( other.rightInput )) || (!this.constraints.equals( other.constraints )) ) {
+            return false;
+        }
+
+        return this.timeWindow.equals( other.timeWindow ) && resultBinder.equals( other.resultBinder ) && Arrays.equals( this.resultConstraints,
+                                                                                                                         other.resultConstraints );
+    }
+
+    public String toString() {
+        return "[ " + this.getClass().getName() + "(" + this.id + ") ]";
+    }
+
+    /**
+     * Creates a BetaMemory for the BetaNode's memory.
+     */
+    public Object createMemory(final RuleBaseConfiguration config) {
+        TimeWindowMemory memory = new TimeWindowMemory();
+    	memory = new TimeWindowMemory();
+    	memory.betaMemory = this.constraints.createBetaMemory( config );
+        //memory.betaMemory = new BetaMemory( new OrderedTupleHashTable(), new OrderedFactHashTable() );
+        memory.workingMemoryContext = this.timeWindow.createWorkingMemoryContext();
+        //memory.orderedEventFactList = new ConcurrentLinkedQueue<EventFactHandle>();
+        //memory.orderedEventTupleList = new ConcurrentLinkedQueue<ReteTuple>();
+        return memory;
+    }
+
+    // returns true if window bounds had to be updated, false otherwise
+    private synchronized boolean updateWindowBounds (long currentTime){
+    	if (windowEnd < currentTime){
+    		myLogger.debug ("Window bounds updated");
+    		windowEnd = currentTime;
+    		windowStart = (windowEnd<windowSize)? 0 : (windowEnd-windowSize+1);
+			return true;
+		}
+		return false;
+    }
+       
+    public synchronized void updateNodeMemory ( final long currentTime, final InternalWorkingMemory workingMemory){
+    	
+    	// remove facts being outside window bounds from items to be considered for aggregation
+    
+	    
+    	EventExpiration<?> temp = orderedExpirationList.peek();
+		if (!orderedExpirationList.isEmpty() && temp.getExpires() <= currentTime){
+			
+			do {
+				if (temp.isOfTypeTuple())
+					eventTuplesToRetract.add((ReteTuple)temp.getEvent());
+				else eventObjectsToRetract.add((InternalFactHandle)temp.getEvent());
+				// remove expired event from queue
+				orderedExpirationList.poll();
+				// get head of queue = next expiration
+				temp = orderedExpirationList.peek();
+			} while (!orderedExpirationList.isEmpty() && temp.getExpires() <= currentTime);
+		
+			// update memory    
+			if (!eventObjectsToRetract.isEmpty()){
+				retractEventObjects(eventObjectsToRetract, workingMemory);
+				eventObjectsToRetract.clear();
+			}
+			
+			if (!eventTuplesToRetract.isEmpty()){
+				retractEventTuples(eventTuplesToRetract, workingMemory);
+				eventTuplesToRetract.clear();
+			}
+		}
+		
+	}
+
+    public void addExpiration (EventExpiration<?> expiration){ // see remarks NodeUpdate
+		//NodeUpdate reminder = new NodeUpdate(expirationTime, node);
+		int index = Collections.binarySearch(orderedExpirationList, expiration, evexComparator);
+		/*if (index < 0)
+			orderedExpirationList.add(-index-1, expiration);
+			*/
+		orderedExpirationList.add(Math.abs(-index-1), expiration);
+	}
+    
+    public static class TimeWindowMemory {
+        private static final long serialVersionUID = 400L;
+        
+        public Object workingMemoryContext;
+        public BetaMemory betaMemory;
+        //public Queue<EventFactHandle> orderedEventFactList;
+        //public Queue<ReteTuple> orderedEventTupleList;
+    }
+
+    private static class TimeWindowResult {
+        // keeping attributes public just for performance
+        public InternalFactHandle handle;
+        public Object             context;
+    }
+    
+    private class EventExpirationComparator  
+	implements Comparator<EventExpiration<?>>{
+
+		@Override
+		public int compare(EventExpiration<?> evex1, EventExpiration<?> evex2) {
+			long t1 = evex1.getExpires(); 
+			long t2 = evex2.getExpires();
+			if (t1 == t2) 
+				return 0;
+			else if (t1 < t2)
+				return -1;
+			else return 1;
+		}
+	
+	}
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleMemory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleMemory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleMemory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,28 @@
+package org.drools.reteoo;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.util.Entry;
+import org.drools.util.Iterator;
+
+public interface TupleMemory {
+    public Iterator iterator();
+
+    public Iterator iterator(InternalFactHandle handle);
+
+    public void add(ReteTuple tuple);
+
+    public ReteTuple remove(ReteTuple tuple);
+
+    public boolean contains(ReteTuple tuple);
+
+    public boolean isIndexed();
+    
+    public ReteTuple peek();
+
+    public int size();
+
+    public Entry[] getTable();
+    
+    public Entry[] toArray();
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleSink.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleSink.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleSink.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,59 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+
+/**
+ * Receiver of propagated <code>ReteTuple</code>s from a
+ * <code>TupleSource</code>.
+ * 
+ * @see TupleSource
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ */
+public interface TupleSink
+    extends
+    Serializable,
+    Sink {
+
+    /**
+     * Assert a new <code>ReteTuple</code>.
+     * 
+     * @param tuple
+     *            The <code>ReteTuple</code> to propagate.
+     * @param context
+     *             The <code>PropagationContext</code> of the <code>WorkingMemory<code> action            
+     * @param workingMemory
+     *            the <code>WorkingMemory</code> session.
+     */
+    void assertTuple(ReteTuple tuple,
+                     PropagationContext context,
+                     InternalWorkingMemory workingMemory);
+
+    void retractTuple(ReteTuple tuple,
+                      PropagationContext context,
+                      InternalWorkingMemory workingMemory);
+    
+    public boolean isTupleMemoryEnabled();
+
+    public void setTupleMemoryEnabled(boolean tupleMemoryEnabled);       
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleSinkNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleSinkNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleSinkNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,59 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Items placed in a <code>LinkedList<code> must implement this interface .
+ * 
+ * @see TupleSinkNodeList
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ */
+public interface TupleSinkNode
+    extends
+    TupleSink {
+
+    /**
+     * Returns the next node
+     * @return
+     *      The next LinkedListNode
+     */
+    public TupleSinkNode getNextTupleSinkNode();
+
+    /**
+     * Sets the next node 
+     * @param next
+     *      The next LinkedListNode
+     */
+    public void setNextTupleSinkNode(TupleSinkNode next);
+
+    /**
+     * Returns the previous node
+     * @return
+     *      The previous LinkedListNode
+     */
+    public TupleSinkNode getPreviousTupleSinkNode();
+
+    /**
+     * Sets the previous node 
+     * @param previous
+     *      The previous LinkedListNode
+     */
+    public void setPreviousTupleSinkNode(TupleSinkNode previous);
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleSinkNodeList.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleSinkNodeList.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleSinkNodeList.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,229 @@
+package org.drools.reteoo;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * This is a simple linked linked implementation. Each node must implement </code>LinkedListNode<code> so that it references
+ * the node before and after it. This way a node can be removed without having to scan the list to find it. This class
+ * does not provide an Iterator implementation as its designed for efficiency and not genericity. There are a number of 
+ * ways to iterate the list.
+ * <p>
+ * Simple iterator:
+ * <pre>
+ * for ( LinkedListNode node = list.getFirst(); node != null; node =  node.getNext() ) {
+ * }
+ * </pre>
+ * 
+ * Iterator that pops the first entry:
+ * <pre>
+ * for ( LinkedListNode node = list.removeFirst(); node != null; node = list.removeFirst() ) {
+ * }
+ * </pre>
+ *
+ *
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ *
+ */
+public class TupleSinkNodeList
+    implements
+    Serializable {
+    private static final long serialVersionUID = 400L;
+
+    private TupleSinkNode     firstNode;
+    private TupleSinkNode     lastNode;
+
+    private int               size;
+
+    /**
+     * Construct an empty <code>LinkedList</code>
+     */
+    public TupleSinkNodeList() {
+
+    }
+
+    /**
+     * Add a <code>TupleSinkNode</code> to the list. If the <code>LinkedList</code> is empty then the first and 
+     * last nodes are set to the added node.
+     * 
+     * @param node
+     *      The <code>TupleSinkNode</code> to be added
+     */
+    public void add(final TupleSinkNode node) {
+        if ( this.firstNode == null ) {
+            this.firstNode = node;
+            this.lastNode = node;;
+        } else {
+            this.lastNode.setNextTupleSinkNode( node );
+            node.setPreviousTupleSinkNode( this.lastNode );
+            this.lastNode = node;
+        }
+        this.size++;
+    }
+
+    /**
+     * Removes a <code>TupleSinkNode</code> from the list. This works by attach the previous reference to the child reference.
+     * When the node to be removed is the first node it calls <code>removeFirst()</code>. When the node to be removed is the last node
+     * it calls <code>removeLast()</code>.
+     * 
+     * @param node
+     *      The <code>TupleSinkNode</code> to be removed.
+     */
+    public void remove(final TupleSinkNode node) {
+        if ( (this.firstNode != node) && (this.lastNode != node) ) {
+            node.getPreviousTupleSinkNode().setNextTupleSinkNode( node.getNextTupleSinkNode() );
+            node.getNextTupleSinkNode().setPreviousTupleSinkNode( node.getPreviousTupleSinkNode() );
+            this.size--;
+            node.setPreviousTupleSinkNode( null );
+            node.setNextTupleSinkNode( null );
+
+        } else {
+            if ( this.firstNode == node ) {
+                removeFirst();
+            } else if ( this.lastNode == node ) {
+                removeLast();
+            }
+        }
+    }
+
+    /**
+     * Return the first node in the list
+     * @return
+     *      The first <code>TupleSinkNode</code>.
+     */
+    public final TupleSinkNode getFirst() {
+        return this.firstNode;
+    }
+
+    /**
+     * Return the last node in the list
+     * @return
+     *      The last <code>TupleSinkNode</code>.
+     */
+    public final TupleSinkNode getLast() {
+        return this.lastNode;
+    }
+
+    /**
+     * Remove the first node from the list. The next node then becomes the first node. If this is the last 
+     * node then both first and last node references are set to null.
+     * 
+     * @return
+     *      The first <code>TupleSinkNode</code>.
+     */
+    public TupleSinkNode removeFirst() {
+        if ( this.firstNode == null ) {
+            return null;
+        }
+        final TupleSinkNode node = this.firstNode;
+        this.firstNode = node.getNextTupleSinkNode();
+        node.setNextTupleSinkNode( null );
+        if ( this.firstNode != null ) {
+            this.firstNode.setPreviousTupleSinkNode( null );
+        } else {
+            this.lastNode = null;
+        }
+        this.size--;
+        return node;
+    }
+
+    /**
+     * Remove the last node from the list. The previous node then becomes the last node. If this is the last 
+     * node then both first and last node references are set to null.
+     * 
+     * @return
+     *      The first <code>TupleSinkNode</code>.
+     */
+    public TupleSinkNode removeLast() {
+        if ( this.lastNode == null ) {
+            return null;
+        }
+        final TupleSinkNode node = this.lastNode;
+        this.lastNode = node.getPreviousTupleSinkNode();
+        node.setPreviousTupleSinkNode( null );
+        if ( this.lastNode != null ) {
+            this.lastNode.setNextTupleSinkNode( null );
+        } else {
+            this.firstNode = this.lastNode;
+        }
+        this.size--;
+        return node;
+    }
+
+    /**
+     * @return
+     *      boolean value indicating the empty status of the list
+     */
+    public final boolean isEmpty() {
+        return (this.firstNode == null);
+    }
+
+    /**
+     * Iterates the list removing all the nodes until there are no more nodes to remove. 
+     */
+    public void clear() {
+        while ( removeFirst() != null ) {
+        }
+    }
+
+    /**
+     * @return
+     *     return size of the list as an int
+     */
+    public final int size() {
+        return this.size;
+    }
+
+    /**
+     * Returns a list iterator
+     * @return
+     */
+    public Iterator iterator() {
+        return new Iterator() {
+            private TupleSinkNode currentNode = null;
+            private TupleSinkNode nextNode    = getFirst();
+
+            public boolean hasNext() {
+                return (this.nextNode != null);
+            }
+
+            public Object next() {
+                this.currentNode = this.nextNode;
+                if ( this.currentNode != null ) {
+                    this.nextNode = this.currentNode.getNextTupleSinkNode();
+                } else {
+                    throw new NoSuchElementException( "No more elements to return" );
+                }
+                return this.currentNode;
+            }
+
+            public void remove() {
+                if ( this.currentNode != null ) {
+                    TupleSinkNodeList.this.remove( this.currentNode );
+                    this.currentNode = null;
+                } else {
+                    throw new IllegalStateException( "No item to remove. Call next() before calling remove()." );
+                }
+            }
+        };
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleSinkPropagator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleSinkPropagator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleSinkPropagator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,59 @@
+package org.drools.reteoo;
+
+import java.io.Serializable;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+
+public interface TupleSinkPropagator
+    extends
+    Serializable {
+    public void propagateAssertTuple(ReteTuple tuple,
+                                     InternalFactHandle handle,
+                                     PropagationContext context,
+                                     InternalWorkingMemory workingMemory);
+
+    public void propagateAssertTuple(ReteTuple tuple,
+                                     PropagationContext context,
+                                     InternalWorkingMemory workingMemory);
+
+    public void propagateRetractTuple(ReteTuple tuple,
+                                      InternalFactHandle handle,
+                                      PropagationContext context,
+                                      InternalWorkingMemory workingMemory);
+
+    public void propagateRetractTuple(ReteTuple tuple,
+                                      PropagationContext context,
+                                      InternalWorkingMemory workingMemory);
+
+    public void createAndPropagateAssertTuple(InternalFactHandle handle,
+                                              PropagationContext context,
+                                              InternalWorkingMemory workingMemory);
+
+    public void createAndPropagateRetractTuple(InternalFactHandle handle,
+                                               PropagationContext context,
+                                               InternalWorkingMemory workingMemory);
+
+    public TupleSink[] getSinks();
+
+    //    public void propagateNewTupleSink(TupleMatch tupleMatch,
+    //                                      PropagationContext context,
+    //                                      InternalWorkingMemory workingMemory);
+    //
+    //    public void propagateNewTupleSink(InternalFactHandle handle,
+    //                                      LinkedList list,
+    //                                      PropagationContext context,
+    //                                      InternalWorkingMemory workingMemory);
+    //
+    //    public void propagateNewTupleSink(ReteTuple tuple,
+    //                                      PropagationContext context,
+    //                                      InternalWorkingMemory workingMemory);
+    //
+    //    public List getPropagatedTuples(final Map memory,
+    //                                    final InternalWorkingMemory workingMemory,
+    //                                    final TupleSink sink);
+
+    public int size();
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleSource.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleSource.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/TupleSource.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,116 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.drools.common.BaseNode;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+
+/**
+ * A source of <code>ReteTuple</code> s for a <code>TupleSink</code>.
+ * 
+ * <p>
+ * Nodes that propagate <code>Tuples</code> extend this class.
+ * </p>
+ * 
+ * @see TupleSource
+ * @see ReteTuple
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ */
+public abstract class TupleSource extends BaseNode
+    implements
+    Serializable {
+    // ------------------------------------------------------------
+    // Instance members
+    // ------------------------------------------------------------
+
+    /** The destination for <code>Tuples</code>. */
+    protected TupleSinkPropagator sink;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    /**
+     * Single parameter constructor that specifies the unique id of the node.
+     * 
+     * @param id
+     */
+    TupleSource(final int id) {
+        super( id );
+        this.sink = EmptyTupleSinkAdapter.getInstance();
+    }
+
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+
+    /**
+     * Adds the <code>TupleSink</code> so that it may receive
+     * <code>Tuples</code> propagated from this <code>TupleSource</code>.
+     * 
+     * @param tupleSink
+     *            The <code>TupleSink</code> to receive propagated
+     *            <code>Tuples</code>.
+     */
+    protected void addTupleSink(final TupleSink tupleSink) {
+        if ( this.sink == EmptyTupleSinkAdapter.getInstance() ) {
+            this.sink = new SingleTupleSinkAdapter( tupleSink );
+        } else if ( this.sink instanceof SingleTupleSinkAdapter ) {
+            final CompositeTupleSinkAdapter sinkAdapter = new CompositeTupleSinkAdapter();
+            sinkAdapter.addTupleSink( this.sink.getSinks()[0] );
+            sinkAdapter.addTupleSink( tupleSink );
+            this.sink = sinkAdapter;
+        } else {
+            ((CompositeTupleSinkAdapter) this.sink).addTupleSink( tupleSink );
+        }
+    }
+
+    /**
+     * Removes the <code>TupleSink</code>
+     * 
+     * @param tupleSink
+     *            The <code>TupleSink</code> to remove
+     */
+    protected void removeTupleSink(final TupleSink tupleSink) {
+        if ( this.sink == EmptyTupleSinkAdapter.getInstance() ) {
+            throw new IllegalArgumentException( "Cannot remove a sink, when the list of sinks is null" );
+        }
+
+        if ( this.sink instanceof SingleTupleSinkAdapter ) {
+            this.sink = EmptyTupleSinkAdapter.getInstance();
+        } else {
+            final CompositeTupleSinkAdapter sinkAdapter = (CompositeTupleSinkAdapter) this.sink;
+            sinkAdapter.removeTupleSink( tupleSink );
+            if ( sinkAdapter.size() == 1 ) {
+                this.sink = new SingleTupleSinkAdapter( sinkAdapter.getSinks()[0] );
+            }
+        }
+    }
+
+    public TupleSinkPropagator getSinkPropagator() {
+        return this.sink;
+    }
+
+    public abstract void updateSink(TupleSink sink,
+                                    PropagationContext context,
+                                    InternalWorkingMemory workingMemory);    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/AccumulateBuilder.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/AccumulateBuilder.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/AccumulateBuilder.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2006 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.builder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.common.BetaConstraints;
+import org.drools.common.TupleStartEqualsConstraint;
+import org.drools.reteoo.AccumulateNode;
+import org.drools.reteoo.ObjectSource;
+import org.drools.reteoo.RightInputAdapterNode;
+import org.drools.reteoo.TupleSource;
+import org.drools.rule.Accumulate;
+import org.drools.rule.RuleConditionElement;
+import org.drools.spi.AlphaNodeFieldConstraint;
+
+/**
+ * @author etirelli
+ *
+ */
+public class AccumulateBuilder
+    implements
+    ReteooComponentBuilder {
+
+    /**
+     * @inheritDoc
+     */
+    public void build(final BuildContext context,
+                      final BuildUtils utils,
+                      final RuleConditionElement rce) {
+        final Accumulate accumulate = (Accumulate) rce;
+        boolean existSubNetwort = false;
+
+        final List resultBetaConstraints = context.getBetaconstraints();
+        final List resultAlphaConstraints = context.getAlphaConstraints();
+
+        final RuleConditionElement source = accumulate.getSource();
+
+        // get builder for the pattern
+        final ReteooComponentBuilder builder = utils.getBuilderFor( source );
+
+        // save tuple source and current pattern offset for later if needed
+        final TupleSource tupleSource = context.getTupleSource();
+        final int currentPatternIndex = context.getCurrentPatternOffset();
+        
+        // builds the source pattern
+        builder.build( context,
+                       utils,
+                       source );
+
+        // if object source is null, then we need to adapt tuple source into a subnetwork
+        if ( context.getObjectSource() == null ) {
+
+            // attach right input adapter node to convert tuple source into an object source
+            context.setObjectSource( (ObjectSource) utils.attachNode( context,
+                                                                      new RightInputAdapterNode( context.getNextId(),
+                                                                                                 context.getTupleSource(),
+                                                                                                 context ) ) );
+
+            // restore tuple source from before the start of the sub network
+            context.setTupleSource( tupleSource );
+
+            // create a tuple start equals constraint and set it in the context
+            final TupleStartEqualsConstraint constraint = TupleStartEqualsConstraint.getInstance();
+            final List betaConstraints = new ArrayList();
+            betaConstraints.add( constraint );
+            context.setBetaconstraints( betaConstraints );
+            existSubNetwort = true;
+        }
+        
+        final BetaConstraints resultsBinder = utils.createBetaNodeConstraint( context,
+                                                                              resultBetaConstraints,
+                                                                              false );
+        final BetaConstraints sourceBinder = utils.createBetaNodeConstraint( context,
+                                                                             context.getBetaconstraints(),
+                                                                             false );
+
+        context.setTupleSource( (TupleSource) utils.attachNode( context,
+                                                                new AccumulateNode( context.getNextId(),
+                                                                                    context.getTupleSource(),
+                                                                                    context.getObjectSource(),
+                                                                                    (AlphaNodeFieldConstraint[]) resultAlphaConstraints.toArray( new AlphaNodeFieldConstraint[resultAlphaConstraints.size()] ),
+                                                                                    sourceBinder,
+                                                                                    resultsBinder,
+                                                                                    accumulate,
+                                                                                    existSubNetwort,
+                                                                                    context ) ) );
+        // source pattern was bound, so nulling context
+        context.setObjectSource( null );
+        context.setCurrentPatternOffset( currentPatternIndex );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean requiresLeftActivation(final BuildUtils utils,
+                                          final RuleConditionElement rce) {
+        return true;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/BuildContext.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/BuildContext.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/BuildContext.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,352 @@
+/*
+ * Copyright 2006 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.builder;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+
+import org.drools.common.BetaConstraints;
+import org.drools.common.InternalRuleBase;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.ObjectSource;
+import org.drools.reteoo.ReteooBuilder;
+import org.drools.reteoo.ReteooRuleBase;
+import org.drools.reteoo.TupleSource;
+import org.drools.rule.EntryPoint;
+import org.drools.rule.RuleConditionElement;
+
+/**
+ * A build context for Reteoo Builder
+ * 
+ * @author etirelli
+ */
+public class BuildContext {
+
+    // tuple source to attach next node to
+    private TupleSource               tupleSource;
+
+    // object source to attach next node to
+    private ObjectSource              objectSource;
+
+    // object type cache to check for cross products
+    private LinkedList                objectType;
+
+    // offset of the pattern
+    private int                       currentPatternOffset;
+
+    // rule base to add rules to
+    private InternalRuleBase          rulebase;
+
+    // working memories attached to the given rulebase
+    private InternalWorkingMemory[]   workingMemories;
+
+    // id generator
+    private ReteooBuilder.IdGenerator idGenerator;
+
+    // a build stack to track nested elements
+    private LinkedList                buildstack;
+
+    // beta constraints from the last pattern attached
+    private List                      betaconstraints;
+
+    // alpha constraints from the last pattern attached
+    private List                      alphaConstraints;
+    
+    // the current entry point
+    private EntryPoint                currentEntryPoint;
+    
+    private boolean                   tupleMemoryEnabled;
+    
+    private boolean                   objectTypeNodeMemoryEnabled;    
+    
+    private boolean                   terminalNodeMemoryEnabled;
+    
+    /** This one is slightly different as alphaMemory can be adaptive, only turning on for new rule attachments */
+    private boolean                   alphaNodeMemoryAllowed;
+
+    public BuildContext(final InternalRuleBase rulebase,
+                        final ReteooBuilder.IdGenerator idGenerator) {
+        this.rulebase = rulebase;
+
+        this.idGenerator = idGenerator;
+        
+        this.workingMemories = null;
+
+        this.objectType = null;
+        this.buildstack = null;
+
+        this.tupleSource = null;
+        this.objectSource = null;
+
+        this.currentPatternOffset = 0;
+        
+        this.tupleMemoryEnabled = true;
+        
+        this.objectTypeNodeMemoryEnabled = true;
+        
+        this.currentEntryPoint = EntryPoint.DEFAULT;
+    }
+
+    /**
+     * @return the currentPatternOffset
+     */
+    public int getCurrentPatternOffset() {
+        return this.currentPatternOffset;
+    }
+
+    /**
+     * @param currentPatternOffset the currentPatternOffset to set
+     */
+    public void setCurrentPatternOffset(final int currentPatternIndex) {
+        this.currentPatternOffset = currentPatternIndex;
+        this.syncObjectTypesWithPatternOffset();
+    }
+
+    public void syncObjectTypesWithPatternOffset() {
+        if (this.objectType == null ) {
+            this.objectType = new LinkedList();
+        }
+        while ( this.objectType.size() > this.currentPatternOffset ) {
+            this.objectType.removeLast();
+        }
+    }
+
+    /**
+     * @return the objectSource
+     */
+    public ObjectSource getObjectSource() {
+        return this.objectSource;
+    }
+
+    /**
+     * @param objectSource the objectSource to set
+     */
+    public void setObjectSource(final ObjectSource objectSource) {
+        this.objectSource = objectSource;
+    }
+
+    /**
+     * @return the objectType
+     */
+    public LinkedList getObjectType() {
+        if (this.objectType == null ) {
+            this.objectType = new LinkedList();
+        }        
+        return this.objectType;
+    }
+
+    /**
+     * @param objectType the objectType to set
+     */
+    public void setObjectType(final LinkedList objectType) {
+        if (this.objectType == null ) {
+            this.objectType = new LinkedList();
+        }        
+        this.objectType = objectType;
+    }
+
+    /**
+     * @return the tupleSource
+     */
+    public TupleSource getTupleSource() {
+        return this.tupleSource;
+    }
+
+    /**
+     * @param tupleSource the tupleSource to set
+     */
+    public void setTupleSource(final TupleSource tupleSource) {
+        this.tupleSource = tupleSource;
+    }
+
+    public void incrementCurrentPatternOffset() {
+        this.currentPatternOffset++;
+    }
+
+    public void decrementCurrentPatternOffset() {
+        this.currentPatternOffset--;
+        this.syncObjectTypesWithPatternOffset();
+    }
+
+    /**
+     * Returns context rulebase
+     * @return
+     */
+    public InternalRuleBase getRuleBase() {
+        return this.rulebase;
+    }
+
+    /**
+     * Return the array of working memories associated with the given
+     * rulebase.
+     * 
+     * @return
+     */
+    public InternalWorkingMemory[] getWorkingMemories() {
+        if ( this.workingMemories == null ) {
+            this.workingMemories = (InternalWorkingMemory[]) this.rulebase.getWorkingMemories();
+        }
+        return this.workingMemories;
+    }
+
+    /**
+     * Returns an Id for the next node
+     * @return
+     */
+    public int getNextId() {
+        return this.idGenerator.getNextId();
+    }
+
+    /**
+     * Method used to undo previous id assignment
+     */
+    public void releaseLastId() {
+        this.idGenerator.releaseLastId();
+    }
+
+    /**
+     * Adds the rce to the build stack
+     * @param rce
+     */
+    public void push(final RuleConditionElement rce) {
+        if ( this.buildstack == null ) {
+            this.buildstack = new LinkedList();            
+        }        
+        this.buildstack.addLast( rce );
+    }
+
+    /**
+     * Removes the top stack element
+     * @return
+     */
+    public RuleConditionElement pop() {
+        if ( this.buildstack == null ) {
+            this.buildstack = new LinkedList();            
+        }
+        return (RuleConditionElement) this.buildstack.removeLast();
+    }
+
+    /**
+     * Returns the top stack element without removing it
+     * @return
+     */
+    public RuleConditionElement peek() {
+        if ( this.buildstack == null ) {
+            this.buildstack = new LinkedList();            
+        }        
+        return (RuleConditionElement) this.buildstack.getLast();
+    }
+
+    /**
+     * Returns a list iterator to iterate over the stacked elements
+     * @return
+     */
+    public ListIterator stackIterator() {
+        if ( this.buildstack == null ) {
+            this.buildstack = new LinkedList();            
+        }        
+        return this.buildstack.listIterator();
+    }
+
+    /**
+     * @return the betaconstraints
+     */
+    public List getBetaconstraints() {
+        return this.betaconstraints;
+    }
+
+    /**
+     * @param betaconstraints the betaconstraints to set
+     */
+    public void setBetaconstraints(final List betaconstraints) {
+        this.betaconstraints = betaconstraints;
+    }   
+    
+    public int getNextSequence(String groupName) {
+        //List list = new ArrayList();
+        
+        Integer seq = ( Integer ) this.rulebase.getAgendaGroupRuleTotals().get( groupName );
+        if ( seq == null ) {
+            seq = new Integer( 0 );            
+        }
+        Integer newSeq = new Integer( seq.intValue() + 1 );
+        this.rulebase.getAgendaGroupRuleTotals().put( groupName, newSeq );
+        
+        return newSeq.intValue();
+    }
+
+    /**
+     * @return
+     */
+    public List getAlphaConstraints() {
+        return alphaConstraints;
+    }
+
+    public void setAlphaConstraints(List alphaConstraints) {
+        this.alphaConstraints = alphaConstraints;
+    }
+
+    public boolean isTupleMemoryEnabled() {
+        return this.tupleMemoryEnabled;
+    }
+
+    public void setTupleMemoryEnabled(boolean hasLeftMemory) {
+        this.tupleMemoryEnabled = hasLeftMemory;
+    }
+
+    public boolean isObjectTypeNodeMemoryEnabled() {
+        return objectTypeNodeMemoryEnabled;
+    }
+
+    public void setObjectTypeNodeMemoryEnabled(boolean hasObjectTypeMemory) {
+        this.objectTypeNodeMemoryEnabled = hasObjectTypeMemory;
+    }
+
+    public boolean isTerminalNodeMemoryEnabled() {
+        return terminalNodeMemoryEnabled;
+    }
+
+    public void setTerminalNodeMemoryEnabled(boolean hasTerminalNodeMemory) {
+        this.terminalNodeMemoryEnabled = hasTerminalNodeMemory;
+    }     
+    
+    public void setAlphaNodeMemoryAllowed(boolean alphaMemoryAllowed) {
+        this.alphaNodeMemoryAllowed = alphaMemoryAllowed;
+    }
+    
+    public boolean isAlphaMemoryAllowed() {
+        return this.alphaNodeMemoryAllowed;
+    }
+
+    /**
+     * @return the currentEntryPoint
+     */
+    public EntryPoint getCurrentEntryPoint() {
+        return currentEntryPoint;
+    }
+
+    /**
+     * @param currentEntryPoint the currentEntryPoint to set
+     */
+    public void setCurrentEntryPoint(EntryPoint currentEntryPoint) {
+        this.currentEntryPoint = currentEntryPoint;
+    }
+        
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/BuildUtils.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/BuildUtils.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/BuildUtils.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2006 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.builder;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.common.BaseNode;
+import org.drools.common.BetaConstraints;
+import org.drools.common.DefaultBetaConstraints;
+import org.drools.common.DoubleBetaConstraints;
+import org.drools.common.EmptyBetaConstraints;
+import org.drools.common.QuadroupleBetaConstraints;
+import org.drools.common.SingleBetaConstraints;
+import org.drools.common.TripleBetaConstraints;
+import org.drools.reteoo.EntryPointNode;
+import org.drools.reteoo.ObjectSink;
+import org.drools.reteoo.ObjectSource;
+import org.drools.reteoo.ObjectTypeNode;
+import org.drools.reteoo.TupleSink;
+import org.drools.reteoo.TupleSource;
+import org.drools.rule.Declaration;
+import org.drools.rule.InvalidPatternException;
+import org.drools.rule.RuleConditionElement;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.spi.ObjectType;
+
+/**
+ * Utility functions for reteoo build
+ * 
+ * @author etirelli
+ */
+public class BuildUtils {
+
+    private final Map componentBuilders = new HashMap();
+
+    /**
+     * Adds the given builder for the given target to the builders map
+     * 
+     * @param target
+     * @param builder
+     */
+    public void addBuilder(final Class target,
+                           final ReteooComponentBuilder builder) {
+        this.componentBuilders.put( target,
+                                    builder );
+    }
+
+    /**
+     * Returns a builder for the given target from the builders map
+     * 
+     * @param target
+     * @return returns null if not found
+     */
+    public ReteooComponentBuilder getBuilderFor(final RuleConditionElement target) {
+        return (ReteooComponentBuilder) this.componentBuilders.get( target.getClass() );
+    }
+
+    /**
+     * Attaches a node into the network. If a node already exists that could
+     * substitute, it is used instead.
+     *
+     * @param context
+     *            The current build context
+     * @param candidate
+     *            The node to attach.
+     *            
+     * @return the actual attached node that may be the one given as parameter
+     *         or eventually one that was already in the cache if sharing is enabled
+     */
+    public BaseNode attachNode(final BuildContext context,
+                               final BaseNode candidate) {
+        BaseNode node = null;
+        if( candidate instanceof EntryPointNode ) {
+            // entry point nodes are always shared
+            EntryPointNode epn = context.getRuleBase().getRete().getEntryPointNode( ((EntryPointNode)candidate).getEntryPoint() );
+            if( epn != null ) {
+                node = epn;
+            }
+        } else if( candidate instanceof ObjectTypeNode ) {
+            // object type nodes are always shared
+            ObjectTypeNode otn = (ObjectTypeNode) candidate;
+            Map<ObjectType, ObjectTypeNode> map = context.getRuleBase().getRete().getObjectTypeNodes( context.getCurrentEntryPoint() );
+            if( map != null ) {
+                otn = map.get( otn.getObjectType() );
+                if ( otn != null ) {
+                    node = otn;
+                }
+            }
+        } else if( isSharingEnabledForNode( context, candidate ) ) {
+            if ( (context.getTupleSource() != null) && ( candidate instanceof TupleSink ) ) {
+                TupleSink[] sinks = context.getTupleSource().getSinkPropagator().getSinks(); 
+                for( int i = 0; i < sinks.length; i++ ) {
+                    if( candidate.equals( sinks[i] ) ) {
+                        node = (BaseNode) sinks[i];
+                        break;
+                    }
+                }
+            } else if ( (context.getObjectSource() != null) && (candidate instanceof ObjectSink) ) {
+                ObjectSink[] sinks = context.getObjectSource().getSinkPropagator().getSinks();
+                for( int i = 0; i < sinks.length; i++ ) {
+                    if( candidate.equals( sinks[i] ) ) {
+                        node = (BaseNode) sinks[i];
+                        break;
+                    }
+                }
+            } else {
+                throw new RuntimeDroolsException( "This is a bug on node sharing verification. Please report to development team." );
+            }
+            if( node != null ) {
+                // shared node found
+                // undo previous id assignment
+                context.releaseLastId();
+                node.addShare();
+            }
+        }
+        
+
+        if ( node == null ) {
+            // only attach() if it is a new node
+            node = candidate;
+            if ( context.getWorkingMemories().length == 0 ) {
+                node.attach();
+            } else {
+                node.attach( context.getWorkingMemories() );
+            }
+        }
+        return node;
+        
+    }
+
+    /**
+     * Utility function to check if sharing is enabled for nodes of the given class
+     * 
+     * @param context
+     * @param node
+     * @return
+     */
+    private boolean isSharingEnabledForNode(final BuildContext context,
+                                            final BaseNode node) {
+        if ( node instanceof TupleSource ) {
+            return context.getRuleBase().getConfiguration().isShareBetaNodes();
+        } else if ( node instanceof ObjectSource ) {
+            return context.getRuleBase().getConfiguration().isShareAlphaNodes();
+        }
+        return false;
+    }
+
+    /**
+     * Creates and returns a BetaConstraints object for the given list of constraints
+     * 
+     * @param context the current build context
+     * @param list the list of constraints
+     * 
+     * @return
+     */
+    public BetaConstraints createBetaNodeConstraint(final BuildContext context,
+                                                    final List list,
+                                                    final boolean disableIndexing ) {
+        BetaConstraints constraints;
+        switch ( list.size() ) {
+            case 0 :
+                constraints = EmptyBetaConstraints.getInstance();
+                break;
+            case 1 :
+                constraints = new SingleBetaConstraints( (BetaNodeFieldConstraint) list.get( 0 ),
+                                                         context.getRuleBase().getConfiguration(),
+                                                         disableIndexing );
+                break;
+            case 2 :
+                constraints = new DoubleBetaConstraints( (BetaNodeFieldConstraint[]) list.toArray( new BetaNodeFieldConstraint[list.size()] ),
+                                                         context.getRuleBase().getConfiguration(),
+                                                         disableIndexing  );
+                break;
+            case 3 :
+                constraints = new TripleBetaConstraints( (BetaNodeFieldConstraint[]) list.toArray( new BetaNodeFieldConstraint[list.size()] ),
+                                                         context.getRuleBase().getConfiguration(),
+                                                         disableIndexing  );
+                break;
+            case 4 :
+                constraints = new QuadroupleBetaConstraints( (BetaNodeFieldConstraint[]) list.toArray( new BetaNodeFieldConstraint[list.size()] ),
+                                                             context.getRuleBase().getConfiguration(),
+                                                             disableIndexing  );
+                break;
+            default :
+                constraints = new DefaultBetaConstraints( (BetaNodeFieldConstraint[]) list.toArray( new BetaNodeFieldConstraint[list.size()] ),
+                                                          context.getRuleBase().getConfiguration(),
+                                                          disableIndexing  );
+        }
+        return constraints;
+    }
+
+    /**
+     * Make sure the required declarations are previously bound
+     * 
+     * @param declarations
+     * @throws InvalidPatternException
+     */
+    public void checkUnboundDeclarations(final BuildContext context,
+                                         final Declaration[] declarations) throws InvalidPatternException {
+        final List list = new ArrayList();
+        for ( int i = 0, length = declarations.length; i < length; i++ ) {
+            for ( final ListIterator it = context.stackIterator(); it.hasPrevious(); ) {
+                final RuleConditionElement rce = (RuleConditionElement) it.previous();
+                final Declaration decl = rce.resolveDeclaration( declarations[i].getIdentifier() );
+                if ( decl == null || decl.getPattern().getOffset() > declarations[i].getPattern().getOffset() ) {
+                    list.add( declarations[i].getIdentifier() );
+                }
+            }
+        }
+
+        // Make sure the required declarations        
+        if ( list.size() != 0 ) {
+            final StringBuffer buffer = new StringBuffer();
+            buffer.append( list.get( 0 ) );
+            for ( int i = 1, size = list.size(); i < size; i++ ) {
+                buffer.append( ", " + list.get( i ) );
+            }
+
+            throw new InvalidPatternException( "Required Declarations not bound: '" + buffer );
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/CollectBuilder.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/CollectBuilder.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/CollectBuilder.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2006 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.builder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.common.BetaConstraints;
+import org.drools.common.TupleStartEqualsConstraint;
+import org.drools.reteoo.CollectNode;
+import org.drools.reteoo.ObjectSource;
+import org.drools.reteoo.RightInputAdapterNode;
+import org.drools.reteoo.TupleSource;
+import org.drools.rule.Collect;
+import org.drools.rule.Pattern;
+import org.drools.rule.RuleConditionElement;
+import org.drools.spi.AlphaNodeFieldConstraint;
+
+/**
+ * @author etirelli
+ *
+ */
+public class CollectBuilder
+    implements
+    ReteooComponentBuilder {
+
+    /**
+     * @inheritDoc
+     */
+    public void build(final BuildContext context,
+                      final BuildUtils utils,
+                      final RuleConditionElement rce) {
+
+        boolean existSubNetwort = false;
+        final Collect collect = (Collect) rce;
+
+        final List resultBetaConstraints = context.getBetaconstraints();
+        final List resultAlphaConstraints = context.getAlphaConstraints();
+
+        final Pattern sourcePattern = collect.getSourcePattern();
+
+        // get builder for the pattern
+        final ReteooComponentBuilder builder = utils.getBuilderFor( sourcePattern );
+
+        // save tuple source and pattern offset for later if needed
+        final TupleSource tupleSource = context.getTupleSource();
+        final int currentPatternIndex = context.getCurrentPatternOffset();
+        
+        // builds the source pattern
+        builder.build( context,
+                       utils,
+                       sourcePattern );
+
+        // if object source is null, then we need to adapt tuple source into a subnetwork
+        if ( context.getObjectSource() == null ) {
+
+            // attach right input adapter node to convert tuple source into an object source
+            context.setObjectSource( (ObjectSource) utils.attachNode( context,
+                                                                      new RightInputAdapterNode( context.getNextId(),
+                                                                                                 context.getTupleSource(),
+                                                                                                 context ) ) );
+
+            // restore tuple source from before the start of the sub network
+            context.setTupleSource( tupleSource );
+
+            // create a tuple start equals constraint and set it in the context
+            final TupleStartEqualsConstraint constraint = TupleStartEqualsConstraint.getInstance();
+            final List betaConstraints = new ArrayList();
+            betaConstraints.add( constraint );
+            context.setBetaconstraints( betaConstraints );
+            existSubNetwort = true;
+        }
+        
+        BetaConstraints binder = utils.createBetaNodeConstraint( context, context.getBetaconstraints(), false );
+        BetaConstraints resultBinder = utils.createBetaNodeConstraint( context, resultBetaConstraints, false );
+        
+        context.setTupleSource( (TupleSource) utils.attachNode( context,
+                                                                new CollectNode( context.getNextId(),
+                                                                                 context.getTupleSource(),
+                                                                                 context.getObjectSource(),
+                                                                                 (AlphaNodeFieldConstraint[]) resultAlphaConstraints.toArray( new AlphaNodeFieldConstraint[resultAlphaConstraints.size()] ),
+                                                                                 binder, // source binder
+                                                                                 resultBinder,
+                                                                                 collect,
+                                                                                 existSubNetwort,
+                                                                                 context ) ) );
+        // source pattern was bound, so nulling context
+        context.setObjectSource( null );
+        context.setCurrentPatternOffset( currentPatternIndex );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean requiresLeftActivation(final BuildUtils utils,
+                                          final RuleConditionElement rce) {
+        return true;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/EntryPointBuilder.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/EntryPointBuilder.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/EntryPointBuilder.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 14, 2007
+ */
+package org.drools.reteoo.builder;
+
+import org.drools.rule.EntryPoint;
+import org.drools.rule.RuleConditionElement;
+
+/**
+ * This is a builder for the entry point pattern
+ * source.
+ *  
+ * @author etirelli
+ */
+public class EntryPointBuilder
+    implements
+    ReteooComponentBuilder {
+
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.builder.ReteooComponentBuilder#build(org.drools.reteoo.builder.BuildContext, org.drools.reteoo.builder.BuildUtils, org.drools.rule.RuleConditionElement)
+     */
+    public void build(BuildContext context,
+                      BuildUtils utils,
+                      RuleConditionElement rce) {
+        final EntryPoint entry = (EntryPoint) rce;
+        
+        context.setCurrentEntryPoint( entry );
+     }
+
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.builder.ReteooComponentBuilder#requiresLeftActivation(org.drools.reteoo.builder.BuildUtils, org.drools.rule.RuleConditionElement)
+     */
+    public boolean requiresLeftActivation(BuildUtils utils,
+                                          RuleConditionElement rce) {
+        return true;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/EvalBuilder.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/EvalBuilder.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/EvalBuilder.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2006 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.builder;
+
+import org.drools.reteoo.EvalConditionNode;
+import org.drools.reteoo.TupleSource;
+import org.drools.rule.EvalCondition;
+import org.drools.rule.RuleConditionElement;
+
+/**
+ * @author etirelli
+ *
+ */
+public class EvalBuilder
+    implements
+    ReteooComponentBuilder {
+
+    /**
+     * @inheritDoc
+     */
+    public void build(final BuildContext context,
+                      final BuildUtils utils,
+                      final RuleConditionElement rce) {
+
+        final EvalCondition eval = (EvalCondition) rce;
+        utils.checkUnboundDeclarations( context,
+                                        eval.getRequiredDeclarations() );
+        context.setTupleSource( (TupleSource) utils.attachNode( context,
+                                                                new EvalConditionNode( context.getNextId(),
+                                                                                       context.getTupleSource(),
+                                                                                       eval,
+                                                                                       context ) ) );
+
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean requiresLeftActivation(final BuildUtils utils,
+                                          final RuleConditionElement rce) {
+        return true;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/ForallBuilder.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/ForallBuilder.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/ForallBuilder.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2006 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.builder;
+
+import java.util.Iterator;
+
+import org.drools.rule.Pattern;
+import org.drools.rule.Forall;
+import org.drools.rule.GroupElement;
+import org.drools.rule.GroupElementFactory;
+import org.drools.rule.RuleConditionElement;
+
+/**
+ * The Reteoo component builder for forall CE
+ * 
+ * @author etirelli
+ */
+public class ForallBuilder
+    implements
+    ReteooComponentBuilder {
+
+    /**
+     * @inheritDoc
+     */
+    public void build(final BuildContext context,
+                      final BuildUtils utils,
+                      final RuleConditionElement rce) {
+        final Forall forall = (Forall) rce;
+
+        // forall can be translated into
+        // not( basePattern and not( <remaining_patterns>+ ) ) 
+        // so we just do that:
+
+        final GroupElement and = GroupElementFactory.newAndInstance();
+        and.addChild( forall.getBasePattern() );
+
+        final GroupElement not2 = GroupElementFactory.newNotInstance();
+        if ( forall.getRemainingPatterns().size() == 1 ) {
+            not2.addChild( (Pattern) forall.getRemainingPatterns().get( 0 ) );
+            and.addChild( not2 );
+        } else if ( forall.getRemainingPatterns().size() > 1 ) {
+            final GroupElement and2 = GroupElementFactory.newAndInstance();
+            for ( final Iterator it = forall.getRemainingPatterns().iterator(); it.hasNext(); ) {
+                and2.addChild( (Pattern) it.next() );
+            }
+            not2.addChild( and2 );
+            and.addChild( not2 );
+        }
+
+        final GroupElement not = GroupElementFactory.newNotInstance();
+        not.addChild( and );
+
+        // get builder for the CEs
+        final ReteooComponentBuilder builder = utils.getBuilderFor( not );
+
+        // builds the CEs
+        builder.build( context,
+                       utils,
+                       not );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean requiresLeftActivation(final BuildUtils utils,
+                                          final RuleConditionElement rce) {
+        return true;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/FromBuilder.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/FromBuilder.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/FromBuilder.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2006 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.builder;
+
+import java.util.Collections;
+
+import org.drools.common.BetaConstraints;
+import org.drools.reteoo.FromNode;
+import org.drools.reteoo.TupleSource;
+import org.drools.rule.From;
+import org.drools.rule.RuleConditionElement;
+import org.drools.spi.AlphaNodeFieldConstraint;
+
+/**
+ * @author etirelli
+ *
+ */
+public class FromBuilder
+    implements
+    ReteooComponentBuilder {
+
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.builder.ReteooComponentBuilder#build(org.drools.reteoo.builder.BuildContext, org.drools.reteoo.builder.BuildUtils, org.drools.rule.RuleConditionElement)
+     */
+    public void build(final BuildContext context,
+                      final BuildUtils utils,
+                      final RuleConditionElement rce) {
+        final From from = (From) rce;
+
+        BetaConstraints betaConstraints = utils.createBetaNodeConstraint( context, context.getBetaconstraints(), true );
+        
+        context.setTupleSource( (TupleSource) utils.attachNode( context,
+                                                                new FromNode( context.getNextId(),
+                                                                              from.getDataProvider(),
+                                                                              context.getTupleSource(),
+                                                                              (AlphaNodeFieldConstraint[]) context.getAlphaConstraints().toArray( new AlphaNodeFieldConstraint[context.getAlphaConstraints().size()] ),
+                                                                              betaConstraints ) ) );
+        context.setAlphaConstraints( null );
+        context.setBetaconstraints( null );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean requiresLeftActivation(final BuildUtils utils,
+                                          final RuleConditionElement rce) {
+        return true;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/GroupElementBuilder.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/GroupElementBuilder.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/GroupElementBuilder.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,340 @@
+/*
+ * Copyright 2006 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.builder;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.common.BetaConstraints;
+import org.drools.common.TupleStartEqualsConstraint;
+import org.drools.reteoo.ExistsNode;
+import org.drools.reteoo.JoinNode;
+import org.drools.reteoo.LeftInputAdapterNode;
+import org.drools.reteoo.NotNode;
+import org.drools.reteoo.ObjectSource;
+import org.drools.reteoo.RightInputAdapterNode;
+import org.drools.reteoo.TupleSource;
+import org.drools.rule.GroupElement;
+import org.drools.rule.RuleConditionElement;
+
+/**
+ * @author etirelli
+ *
+ */
+public class GroupElementBuilder
+    implements
+    ReteooComponentBuilder {
+
+    private final Map geBuilders = new HashMap();
+
+    public GroupElementBuilder() {
+        this.geBuilders.put( GroupElement.AND,
+                             new AndBuilder() );
+        this.geBuilders.put( GroupElement.OR,
+                             new OrBuilder() );
+        this.geBuilders.put( GroupElement.NOT,
+                             new NotBuilder() );
+        this.geBuilders.put( GroupElement.EXISTS,
+                             new ExistsBuilder() );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public void build(final BuildContext context,
+                      final BuildUtils utils,
+                      final RuleConditionElement rce) {
+        final GroupElement ge = (GroupElement) rce;
+
+        final ReteooComponentBuilder builder = (ReteooComponentBuilder) this.geBuilders.get( ge.getType() );
+
+        builder.build( context,
+                       utils,
+                       rce );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean requiresLeftActivation(final BuildUtils utils,
+                                          final RuleConditionElement rce) {
+        final GroupElement ge = (GroupElement) rce;
+
+        final ReteooComponentBuilder builder = (ReteooComponentBuilder) this.geBuilders.get( ge.getType() );
+
+        return builder.requiresLeftActivation( utils,
+                                               rce );
+    }
+
+    private static class AndBuilder
+        implements
+        ReteooComponentBuilder {
+
+        /**
+         * @inheritDoc
+         * 
+         * And group elements just iterate over their children
+         * selecting and calling the build procedure for each one
+         * 
+         */
+        public void build(final BuildContext context,
+                          final BuildUtils utils,
+                          final RuleConditionElement rce) {
+
+            final GroupElement ge = (GroupElement) rce;
+
+            // iterate over each child and build it
+            for ( final Iterator it = ge.getChildren().iterator(); it.hasNext(); ) {
+
+                final RuleConditionElement child = (RuleConditionElement) it.next();
+
+                final ReteooComponentBuilder builder = utils.getBuilderFor( child );
+
+                builder.build( context,
+                               utils,
+                               child );
+
+                // if a previous object source was bound, but no tuple source
+                if ( context.getObjectSource() != null && context.getTupleSource() == null ) {
+                    // adapt it to a Tuple source
+                    context.setTupleSource( (TupleSource) utils.attachNode( context,
+                                                                            new LeftInputAdapterNode( context.getNextId(),
+                                                                                                      context.getObjectSource(),
+                                                                                                      context ) ) );
+
+                    context.setObjectSource( null );
+                }
+
+                // if there was a previous tuple source, then a join node is needed
+                if ( context.getObjectSource() != null && context.getTupleSource() != null ) {
+                    // so, create the tuple source and clean up the constraints and object source
+                    final BetaConstraints betaConstraints = utils.createBetaNodeConstraint( context,
+                                                                                            context.getBetaconstraints(),
+                                                                                            false );
+                    
+                    context.setTupleSource( (TupleSource) utils.attachNode( context,
+                                                                            new JoinNode( context.getNextId(),
+                                                                                          context.getTupleSource(),
+                                                                                          context.getObjectSource(),
+                                                                                          betaConstraints,
+                                                                                          context ) ) );
+                    context.setBetaconstraints( null );
+                    context.setObjectSource( null );
+                }
+            }
+        }
+
+        public boolean requiresLeftActivation(final BuildUtils utils,
+                                              final RuleConditionElement rce) {
+            final GroupElement and = (GroupElement) rce;
+
+            // need to check this because in the case of an empty rule, the root AND
+            // will have no child
+            if ( and.getChildren().isEmpty() ) {
+                return true;
+            }
+
+            final RuleConditionElement child = (RuleConditionElement) and.getChildren().get( 0 );
+            final ReteooComponentBuilder builder = utils.getBuilderFor( child );
+
+            return builder.requiresLeftActivation( utils,
+                                                   child );
+        }
+    }
+
+    private static class OrBuilder
+        implements
+        ReteooComponentBuilder {
+
+        /**
+         * @inheritDoc
+         */
+        public void build(final BuildContext context,
+                          final BuildUtils utils,
+                          final RuleConditionElement rce) {
+            throw new RuntimeDroolsException( "BUG: Can't build a rete network with an inner OR group element" );
+        }
+
+        public boolean requiresLeftActivation(final BuildUtils utils,
+                                              final RuleConditionElement rce) {
+            throw new RuntimeDroolsException( "BUG: Can't build a rete network with an inner OR group element" );
+        }
+    }
+
+    private static class NotBuilder
+        implements
+        ReteooComponentBuilder {
+
+        /**
+         * @inheritDoc
+         * 
+         * Not must verify what is the class of its child:
+         * 
+         * If it is a pattern, a simple NotNode is added to the rulebase
+         * If it is a group element, than a subnetwork must be created
+         */
+        public void build(final BuildContext context,
+                          final BuildUtils utils,
+                          final RuleConditionElement rce) {
+            final GroupElement not = (GroupElement) rce;
+
+            // NOT must save some context info to restore it later
+            final int currentPatternIndex = context.getCurrentPatternOffset();
+            final TupleSource tupleSource = context.getTupleSource();
+
+            // get child
+            final RuleConditionElement child = (RuleConditionElement) not.getChildren().get( 0 );
+
+            // get builder for child
+            final ReteooComponentBuilder builder = utils.getBuilderFor( child );
+
+            // builds the child
+            builder.build( context,
+                           utils,
+                           child );
+
+            // if it is a subnetwork
+            if ( context.getObjectSource() == null && context.getTupleSource() != null ) {
+
+                // attach right input adapter node to convert tuple source into an object source
+                context.setObjectSource( (ObjectSource) utils.attachNode( context,
+                                                                          new RightInputAdapterNode( context.getNextId(),
+                                                                                                     context.getTupleSource(),
+                                                                                                     context ) ) );
+
+                // restore tuple source from before the start of the sub network
+                context.setTupleSource( tupleSource );
+
+                // create a tuple start equals constraint and set it in the context
+                final TupleStartEqualsConstraint constraint = TupleStartEqualsConstraint.getInstance();
+                final List predicates = new ArrayList();
+                predicates.add( constraint );
+                context.setBetaconstraints( predicates );
+
+            }
+
+            final BetaConstraints betaConstraints = utils.createBetaNodeConstraint( context,
+                                                                                    context.getBetaconstraints(),
+                                                                                    false );
+            // then attach the NOT node. It will work both as a simple not node
+            // or as subnetwork join node as the context was set appropriatelly
+            // in each case
+            context.setTupleSource( (TupleSource) utils.attachNode( context,
+                                                                    new NotNode( context.getNextId(),
+                                                                                 context.getTupleSource(),
+                                                                                 context.getObjectSource(),
+                                                                                 betaConstraints,
+                                                                                 context ) ) );
+            context.setBetaconstraints( null );
+            context.setObjectSource( null );
+
+            // restore pattern index
+            context.setCurrentPatternOffset( currentPatternIndex );
+        }
+
+        public boolean requiresLeftActivation(final BuildUtils utils,
+                                              final RuleConditionElement rce) {
+            return true;
+        }
+    }
+
+    private static class ExistsBuilder
+        implements
+        ReteooComponentBuilder {
+
+        /**
+         * @inheritDoc
+         * 
+         * Exists must verify what is the class of its child:
+         * 
+         * If it is a pattern, a simple ExistsNode is added to the rulebase
+         * If it is a group element, than a subnetwork must be created
+         */
+        public void build(final BuildContext context,
+                          final BuildUtils utils,
+                          final RuleConditionElement rce) {
+            final GroupElement exists = (GroupElement) rce;
+
+            // EXISTS must save some context info to restore it later
+            final int currentPatternIndex = context.getCurrentPatternOffset();
+            final TupleSource tupleSource = context.getTupleSource();
+
+            // get child
+            final RuleConditionElement child = (RuleConditionElement) exists.getChildren().get( 0 );
+
+            // get builder for child
+            final ReteooComponentBuilder builder = utils.getBuilderFor( child );
+
+            // builds the child
+            builder.build( context,
+                           utils,
+                           child );
+
+            // if it is a subnetwork
+            if ( context.getObjectSource() == null && context.getTupleSource() != null ) {
+
+                // attach right input adapter node to convert tuple source into an object source
+                context.setObjectSource( (ObjectSource) utils.attachNode( context,
+                                                                          new RightInputAdapterNode( context.getNextId(),
+                                                                                                     context.getTupleSource(),
+                                                                                                     context ) ) );
+
+                // restore tuple source from before the start of the sub network
+                context.setTupleSource( tupleSource );
+
+                // create a tuple start equals constraint and set it in the context
+                final TupleStartEqualsConstraint constraint = TupleStartEqualsConstraint.getInstance();
+                final List predicates = new ArrayList();
+                predicates.add( constraint );
+                context.setBetaconstraints( predicates );
+
+            }
+
+            final BetaConstraints betaConstraints = utils.createBetaNodeConstraint( context,
+                                                                                    context.getBetaconstraints(),
+                                                                                    false );
+
+            // then attach the EXISTS node. It will work both as a simple exists node
+            // or as subnetwork join node as the context was set appropriatelly
+            // in each case
+            context.setTupleSource( (TupleSource) utils.attachNode( context,
+                                                                    new ExistsNode( context.getNextId(),
+                                                                                    context.getTupleSource(),
+                                                                                    context.getObjectSource(),
+                                                                                    betaConstraints,
+                                                                                    context ) ) );
+            context.setBetaconstraints( null );
+            context.setObjectSource( null );
+
+            // restore pattern index
+            context.setCurrentPatternOffset( currentPatternIndex );
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public boolean requiresLeftActivation(final BuildUtils utils,
+                                              final RuleConditionElement rce) {
+            return true;
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/PatternBuilder.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/PatternBuilder.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/PatternBuilder.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,276 @@
+/*
+ * Copyright 2006 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.builder;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.drools.base.ClassObjectType;
+import org.drools.base.DroolsQuery;
+import org.drools.common.InstanceNotEqualsConstraint;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.AlphaNode;
+import org.drools.reteoo.EntryPointNode;
+import org.drools.reteoo.ObjectSource;
+import org.drools.reteoo.ObjectTypeNode;
+import org.drools.reteoo.PropagationQueuingNode;
+import org.drools.rule.Declaration;
+import org.drools.rule.EntryPoint;
+import org.drools.rule.InvalidPatternException;
+import org.drools.rule.Pattern;
+import org.drools.rule.PatternSource;
+import org.drools.rule.RuleConditionElement;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.Constraint;
+import org.drools.spi.ObjectType;
+
+/**
+ * A builder for patterns
+ * 
+ * @author etirelli
+ */
+public class PatternBuilder
+    implements
+    ReteooComponentBuilder {
+
+    /**
+     * @inheritDoc
+     */
+    public void build(final BuildContext context,
+                      final BuildUtils utils,
+                      final RuleConditionElement rce) {
+
+        final Pattern pattern = (Pattern) rce;
+
+        this.attachPattern( context,
+                            utils,
+                            pattern );
+
+    }
+
+    private void attachPattern(final BuildContext context,
+                               final BuildUtils utils,
+                               final Pattern pattern) throws InvalidPatternException {
+
+        // Set pattern offset to the appropriate value
+        pattern.setOffset( context.getCurrentPatternOffset() );
+
+        final List alphaConstraints = new LinkedList();
+        final List betaConstraints = new LinkedList();
+
+        this.createConstraints( context,
+                                utils,
+                                pattern,
+                                alphaConstraints,
+                                betaConstraints );
+
+        // Create BetaConstraints object
+        context.setBetaconstraints( betaConstraints );
+
+        if ( pattern.getSource() != null ) {
+            context.setAlphaConstraints( alphaConstraints );
+            final int currentOffset = context.getCurrentPatternOffset();
+
+            PatternSource source = pattern.getSource();
+
+            ReteooComponentBuilder builder = utils.getBuilderFor( source );
+
+            builder.build( context,
+                           utils,
+                           source );
+            // restoring offset
+            context.setCurrentPatternOffset( currentOffset );
+
+        }
+
+        if ( pattern.getSource() == null || context.getCurrentEntryPoint() != EntryPoint.DEFAULT ) {
+            attachAlphaNodes( context,
+                              utils,
+                              pattern,
+                              alphaConstraints );
+
+            if ( context.getCurrentEntryPoint() != EntryPoint.DEFAULT ) {
+                context.setObjectSource( (ObjectSource) utils.attachNode( context,
+                                                                          new PropagationQueuingNode( context.getNextId(),
+                                                                                                      context.getObjectSource(),
+                                                                                                      context ) ) );
+                // the entry-point specific network nodes are attached, so, set context to default entry-point 
+                context.setCurrentEntryPoint( EntryPoint.DEFAULT );
+            }
+        }
+
+        // last thing to do is increment the offset, since if the pattern has a source,
+        // offset must be overriden
+        context.incrementCurrentPatternOffset();
+    }
+
+    private void createConstraints(BuildContext context,
+                                   BuildUtils utils,
+                                   Pattern pattern,
+                                   List alphaConstraints,
+                                   List betaConstraints) {
+
+        final List constraints = pattern.getConstraints();
+
+        // check if cross products for identity patterns should be disabled
+        checkRemoveIdentities( context,
+                               pattern,
+                               betaConstraints );
+
+        for ( final Iterator it = constraints.iterator(); it.hasNext(); ) {
+            final Object object = it.next();
+            // Check if its a declaration
+            if ( object instanceof Declaration ) {
+                // nothing to be done
+                continue;
+            }
+
+            final Constraint constraint = (Constraint) object;
+            final Declaration[] declarations = constraint.getRequiredDeclarations();
+
+            boolean isAlphaConstraint = true;
+            for ( int i = 0; isAlphaConstraint && i < declarations.length; i++ ) {
+                if ( !declarations[i].isGlobal() && declarations[i].getPattern() != pattern ) {
+                    isAlphaConstraint = false;
+                }
+            }
+
+            if ( isAlphaConstraint ) {
+                alphaConstraints.add( constraint );
+            } else {
+                utils.checkUnboundDeclarations( context,
+                                                constraint.getRequiredDeclarations() );
+                betaConstraints.add( constraint );
+            }
+        }
+    }
+
+    public static ObjectTypeNode attachObjectTypeNode(BuildContext context,
+                                                      ObjectType objectType) {
+        synchronized ( context.getRuleBase().getPackagesMap() ) {
+            InternalWorkingMemory[] wms = context.getWorkingMemories();
+
+            EntryPointNode epn = context.getRuleBase().getRete().getEntryPointNode( context.getCurrentEntryPoint() );
+            if ( epn == null ) {
+                epn = new EntryPointNode( context.getNextId(),
+                                          context.getRuleBase().getRete(),
+                                          context );
+                if ( wms.length > 0 ) {
+                    epn.attach( wms );
+                } else {
+                    epn.attach();
+                }
+            }
+
+            ObjectTypeNode otn = new ObjectTypeNode( context.getNextId(),
+                                                     epn,
+                                                     objectType,
+                                                     context );
+
+            if ( wms.length > 0 ) {
+                otn.attach( wms );
+            } else {
+                otn.attach();
+            }
+
+            return otn;
+        }
+    }
+
+    public void attachAlphaNodes(final BuildContext context,
+                                 final BuildUtils utils,
+                                 final Pattern pattern,
+                                 List alphaConstraints) throws InvalidPatternException {
+
+        // Drools Query ObjectTypeNode never has memory, but other ObjectTypeNode/AlphaNoesNodes may (if not in sequential), 
+        //so need to preserve, so we can resotre after this node is added. LeftMemory  and Terminal remain the same once set.
+
+        boolean objectMemory = context.isObjectTypeNodeMemoryEnabled();
+        boolean alphaMemory = context.isAlphaMemoryAllowed();
+
+        if ( pattern.getObjectType() instanceof ClassObjectType ) {
+            // Is this the query node, if so we don't want any memory
+            if ( DroolsQuery.class == ((ClassObjectType) pattern.getObjectType()).getClassType() ) {
+                context.setTupleMemoryEnabled( false );
+                context.setObjectTypeNodeMemoryEnabled( false );
+                context.setTerminalNodeMemoryEnabled( false );
+                context.setAlphaNodeMemoryAllowed( false );
+            }
+        }
+
+        context.setObjectSource( (ObjectSource) utils.attachNode( context,
+                                                                  new EntryPointNode( context.getNextId(),
+                                                                                      context.getRuleBase().getRete(),
+                                                                                      context ) ) );
+
+        context.setObjectSource( (ObjectSource) utils.attachNode( context,
+                                                                  new ObjectTypeNode( context.getNextId(),
+                                                                                      (EntryPointNode) context.getObjectSource(),
+                                                                                      pattern.getObjectType(),
+                                                                                      context ) ) );
+
+        for ( final Iterator it = alphaConstraints.iterator(); it.hasNext(); ) {
+            final AlphaNodeFieldConstraint constraint = (AlphaNodeFieldConstraint) it.next();
+
+            context.setObjectSource( (ObjectSource) utils.attachNode( context,
+                                                                      new AlphaNode( context.getNextId(),
+                                                                                     (AlphaNodeFieldConstraint) constraint,
+                                                                                     context.getObjectSource(),
+                                                                                     context ) ) );
+        }
+
+        // now restore back to original values
+        context.setObjectTypeNodeMemoryEnabled( objectMemory );
+        context.setAlphaNodeMemoryAllowed( alphaMemory );
+
+    }
+
+    /**
+     * @param context
+     * @param pattern
+     * @param betaConstraints
+     */
+    private void checkRemoveIdentities(final BuildContext context,
+                                       final Pattern pattern,
+                                       final List betaConstraints) {
+        if ( context.getRuleBase().getConfiguration().isRemoveIdentities() && pattern.getObjectType().getClass() == ClassObjectType.class ) {
+            List patterns = null;
+            // Check if this object type exists before
+            // If it does we need stop instance equals cross product
+            final Class thisClass = ((ClassObjectType) pattern.getObjectType()).getClassType();
+            for ( final Iterator it = context.getObjectType().iterator(); it.hasNext(); ) {
+                final Pattern previousPattern = (Pattern) it.next();
+                final Class previousClass = ((ClassObjectType) previousPattern.getObjectType()).getClassType();
+                if ( thisClass.isAssignableFrom( previousClass ) ) {
+                    betaConstraints.add( new InstanceNotEqualsConstraint( previousPattern ) );
+                }
+            }
+
+            // Must be added after the checking, otherwise it matches against itself
+            context.getObjectType().add( pattern );
+        }
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean requiresLeftActivation(final BuildUtils utils,
+                                          final RuleConditionElement rce) {
+        return ((Pattern) rce).getSource() != null;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/ReteooComponentBuilder.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/ReteooComponentBuilder.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/ReteooComponentBuilder.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2006 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.builder;
+
+import org.drools.rule.RuleConditionElement;
+
+/**
+ * An interface for Reteoo Component builders
+ * 
+ * @author etirelli
+ */
+public interface ReteooComponentBuilder {
+
+    /**
+     * Builds and attach if needed the given RuleConditionalElement
+     * 
+     * @param context current build context
+     * @param rce 
+     */
+    public void build(BuildContext context,
+                      BuildUtils utils,
+                      RuleConditionElement rce);
+
+    /**
+     * A boolean function that indicates if the builder requires a previous left 
+     * (tuple) activation in order to correctly build the given component.
+     * 
+     * In other words, if it returns true and no previous TupleSource is already created,
+     * an InitialFact pattern must be added with appropriate left input adapter for 
+     * the network to be correctly built.
+     * 
+     * For instance, NOT / EXISTS / ACCUMULATE / TIMEWINDOW are examples of builders that must return true 
+     * for this method, while PATTERN must return false.
+     * 
+     * @param rce the element to be built
+     * 
+     * @return true if a tuple source is required, false otherwise.
+     */
+    public boolean requiresLeftActivation(BuildUtils utils,
+                                          RuleConditionElement rce);
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/ReteooRuleBuilder.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/ReteooRuleBuilder.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/ReteooRuleBuilder.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2006 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.builder;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.InitialFact;
+import org.drools.RuleIntegrationException;
+import org.drools.base.ClassFieldExtractor;
+import org.drools.base.ClassObjectType;
+import org.drools.base.DroolsQuery;
+import org.drools.base.FieldFactory;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.Operator;
+import org.drools.common.BaseNode;
+import org.drools.common.InternalRuleBase;
+import org.drools.reteoo.QueryTerminalNode;
+import org.drools.reteoo.ReteooBuilder;
+import org.drools.reteoo.ReteooRuleBase;
+import org.drools.reteoo.RuleTerminalNode;
+import org.drools.reteoo.TerminalNode;
+import org.drools.rule.Accumulate;
+import org.drools.rule.Collect;
+import org.drools.rule.EntryPoint;
+import org.drools.rule.Pattern;
+import org.drools.rule.EvalCondition;
+import org.drools.rule.Forall;
+import org.drools.rule.From;
+import org.drools.rule.GroupElement;
+import org.drools.rule.InvalidPatternException;
+import org.drools.rule.LiteralConstraint;
+import org.drools.rule.Query;
+import org.drools.rule.Rule;
+import org.drools.rule.TimeWindow;
+import org.drools.spi.FieldValue;
+
+/**
+ * @author etirelli
+ *
+ */
+public class ReteooRuleBuilder {
+
+    private BuildUtils utils;
+
+    public ReteooRuleBuilder() {
+        this.utils = new BuildUtils();
+
+        this.utils.addBuilder( GroupElement.class,
+                               new GroupElementBuilder() );
+        this.utils.addBuilder( Pattern.class,
+                               new PatternBuilder() );
+        this.utils.addBuilder( EvalCondition.class,
+                               new EvalBuilder() );
+        this.utils.addBuilder( From.class,
+                               new FromBuilder() );
+        this.utils.addBuilder( Collect.class,
+                               new CollectBuilder() );
+        this.utils.addBuilder( Accumulate.class,
+                               new AccumulateBuilder() );
+        this.utils.addBuilder( TimeWindow.class,
+                new TimeWindowBuilder() );
+        this.utils.addBuilder( Forall.class,
+                               new ForallBuilder() );
+        this.utils.addBuilder( EntryPoint.class,
+                               new EntryPointBuilder() );
+    }
+
+    /**
+     * Creates the corresponting Rete network for the given <code>Rule</code> and adds it to
+     * the given rule base.
+     * 
+     * @param rule
+     *            The rule to add.
+     * @param rulebase
+     *            The rulebase to add the rule to.
+     *            
+     * @return a List<BaseNode> of terminal nodes for the rule             
+     * 
+     * @throws RuleIntegrationException
+     *             if an error prevents complete construction of the network for
+     *             the <code>Rule</code>.
+     * @throws InvalidPatternException
+     */
+    public List addRule(final Rule rule,
+                        final InternalRuleBase rulebase,
+                        final ReteooBuilder.IdGenerator idGenerator) throws InvalidPatternException {
+
+        // the list of terminal nodes
+        final List nodes = new ArrayList();
+
+        // transform rule and gets the array of subrules
+        final GroupElement[] subrules = rule.getTransformedLhs();
+
+        for ( int i = 0; i < subrules.length; i++ ) {
+            // creates a clean build context for each subrule
+            final BuildContext context = new BuildContext( rulebase,
+                                                           idGenerator );
+           
+            if ( rulebase.getConfiguration().isSequential() ) {
+                context.setTupleMemoryEnabled( false );
+                context.setObjectTypeNodeMemoryEnabled( false );
+                context.setTerminalNodeMemoryEnabled( false );
+                context.setAlphaNodeMemoryAllowed( false );
+            } else {
+                context.setTupleMemoryEnabled( true );
+                context.setObjectTypeNodeMemoryEnabled( true );
+                context.setTerminalNodeMemoryEnabled( true );
+                context.setAlphaNodeMemoryAllowed( true );                
+            }
+            
+            // adds subrule
+            final TerminalNode node = this.addSubRule( context,
+                                                       subrules[i],
+                                                       rule );
+
+            // adds the terminal node to the list of terminal nodes
+            nodes.add( node );
+
+        }
+
+        return nodes;
+    }
+
+    private TerminalNode addSubRule(final BuildContext context,
+                                    final GroupElement subrule,
+                                    final Rule rule) throws InvalidPatternException {
+        // gets the appropriate builder
+        final ReteooComponentBuilder builder = this.utils.getBuilderFor( subrule );
+
+        // checks if an initial-fact is needed
+        if ( builder.requiresLeftActivation( this.utils,
+                                             subrule ) ) {
+            this.addInitialFactPattern( context,
+                                        subrule,
+                                        rule );
+        }
+
+        // builds and attach
+        builder.build( context,
+                       this.utils,
+                       subrule );
+
+        TerminalNode terminal = null;
+
+        if ( !(rule instanceof Query) ) {
+            // Check a consequence is set
+            if ( rule.getConsequence() == null ) {
+                throw new InvalidPatternException( "Rule '" + rule.getName() + "' has no Consequence" );
+            }
+            terminal = new RuleTerminalNode( context.getNextId(),
+                                             context.getTupleSource(),
+                                             rule,
+                                             subrule,
+                                             context );
+        } else {
+            // Check there is no consequence
+            if ( rule.getConsequence() != null ) {
+                throw new InvalidPatternException( "Query '" + rule.getName() + "' should have no Consequence" );
+            }
+            terminal = new QueryTerminalNode( context.getNextId(),
+                                              context.getTupleSource(),
+                                              rule,
+                                              subrule );
+        }
+        if ( context.getWorkingMemories().length == 0 ) {
+            ((BaseNode) terminal).attach();
+        } else {
+            ((BaseNode) terminal).attach( context.getWorkingMemories() );
+        }
+
+        return terminal;
+    }
+
+    /**
+     * Adds a query pattern to the given subrule
+     * 
+     * @param context
+     * @param subrule
+     * @param query
+     */
+    private void addInitialFactPattern(final BuildContext context,
+                                       final GroupElement subrule,
+                                       final Rule rule) {
+
+        // creates a pattern for initial fact
+        final Pattern pattern = new Pattern( 0,
+                                             new ClassObjectType( InitialFact.class ) );
+
+        // adds the pattern as the first child of the given AND group element
+        subrule.addChild( 0,
+                          pattern );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/TimeWindowBuilder.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/TimeWindowBuilder.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/reteoo/builder/TimeWindowBuilder.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2006 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.builder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.common.BetaConstraints;
+import org.drools.common.TupleStartEqualsConstraint;
+import org.drools.reteoo.TimeWindowNode;
+import org.drools.reteoo.ObjectSource;
+import org.drools.reteoo.RightInputAdapterNode;
+import org.drools.reteoo.TupleSource;
+import org.drools.rule.TimeWindow;
+import org.drools.rule.RuleConditionElement;
+import org.drools.spi.AlphaNodeFieldConstraint;
+
+/**
+ * @author etirelli
+ *
+ */
+public class TimeWindowBuilder
+    implements
+    ReteooComponentBuilder {
+
+    /**
+     * @inheritDoc
+     */
+    public void build(final BuildContext context,
+                      final BuildUtils utils,
+                      final RuleConditionElement rce) {
+        final TimeWindow timeWindow = (TimeWindow) rce;
+        boolean existSubNetwort = false;
+
+        final List resultBetaConstraints = context.getBetaconstraints();
+        final List resultAlphaConstraints = context.getAlphaConstraints();
+
+        final RuleConditionElement source = timeWindow.getSource();
+
+        // get builder for the pattern
+        final ReteooComponentBuilder builder = utils.getBuilderFor( source );
+
+        // save tuple source and current pattern offset for later if needed
+        final TupleSource tupleSource = context.getTupleSource();
+        final int currentPatternIndex = context.getCurrentPatternOffset();
+        
+        // builds the source pattern
+        builder.build( context,
+                       utils,
+                       source );
+
+        // if object source is null, then we need to adapt tuple source into a subnetwork
+        if ( context.getObjectSource() == null ) {
+
+            // attach right input adapter node to convert tuple source into an object source
+            context.setObjectSource( (ObjectSource) utils.attachNode( context,
+                                                                      new RightInputAdapterNode( context.getNextId(),
+                                                                                                 context.getTupleSource(),
+                                                                                                 context ) ) );
+
+            // restore tuple source from before the start of the sub network
+            context.setTupleSource( tupleSource );
+
+            // create a tuple start equals constraint and set it in the context
+            final TupleStartEqualsConstraint constraint = TupleStartEqualsConstraint.getInstance();
+            final List betaConstraints = new ArrayList();
+            betaConstraints.add( constraint );
+            context.setBetaconstraints( betaConstraints );
+            existSubNetwort = true;
+        }
+        
+        final BetaConstraints resultsBinder = utils.createBetaNodeConstraint( context,
+                                                                              resultBetaConstraints,
+                                                                              false );
+        final BetaConstraints sourceBinder = utils.createBetaNodeConstraint( context,
+                                                                             context.getBetaconstraints(),
+                                                                             false );
+
+        context.setTupleSource( (TupleSource) utils.attachNode( context,
+                                                                new TimeWindowNode( context.getNextId(),
+                                                                                    context.getTupleSource(),
+                                                                                    context.getObjectSource(),
+                                                                                    (AlphaNodeFieldConstraint[]) resultAlphaConstraints.toArray( new AlphaNodeFieldConstraint[resultAlphaConstraints.size()] ),
+                                                                                    sourceBinder,
+                                                                                    resultsBinder,
+                                                                                    timeWindow,
+                                                                                    existSubNetwort,
+                                                                                    context ) ) );
+        // source pattern was bound, so nulling context
+        context.setObjectSource( null );
+        context.setCurrentPatternOffset( currentPatternIndex );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean requiresLeftActivation(final BuildUtils utils,
+                                          final RuleConditionElement rce) {
+        return true;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/AbstractCompositeConstraint.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/AbstractCompositeConstraint.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/AbstractCompositeConstraint.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2006 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.rule;
+
+import java.util.Arrays;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.spi.Constraint;
+import org.drools.util.ArrayUtils;
+
+/**
+ * A superclass for all composite constraints, like "OR" and "AND"
+ * 
+ * @author etirelli
+ */
+public abstract class AbstractCompositeConstraint
+    implements
+    AlphaNodeFieldConstraint,
+    BetaNodeFieldConstraint {
+
+    protected AlphaNodeFieldConstraint[] alphaConstraints     = new AlphaNodeFieldConstraint[0];
+    protected BetaNodeFieldConstraint[]  betaConstraints      = new BetaNodeFieldConstraint[0];
+    protected Declaration[]              requiredDeclarations = new Declaration[0];
+
+    /**
+     * Adds an alpha constraint to the multi field OR constraint
+     * 
+     * @param constraint
+     */
+    public void addAlphaConstraint(AlphaNodeFieldConstraint constraint) {
+        if ( constraint != null ) {
+            AlphaNodeFieldConstraint[] tmp = this.alphaConstraints;
+            this.alphaConstraints = new AlphaNodeFieldConstraint[tmp.length + 1];
+            System.arraycopy( tmp,
+                              0,
+                              this.alphaConstraints,
+                              0,
+                              tmp.length );
+            this.alphaConstraints[this.alphaConstraints.length - 1] = constraint;
+            this.updateRequiredDeclarations( constraint );
+        }
+    }
+
+    /**
+     * Adds a beta constraint to this multi field OR constraint
+     * @param constraint
+     */
+    public void addBetaConstraint(BetaNodeFieldConstraint constraint) {
+        if ( constraint != null ) {
+            BetaNodeFieldConstraint[] tmp = this.betaConstraints;
+            this.betaConstraints = new BetaNodeFieldConstraint[tmp.length + 1];
+            System.arraycopy( tmp,
+                              0,
+                              this.betaConstraints,
+                              0,
+                              tmp.length );
+            this.betaConstraints[this.betaConstraints.length - 1] = constraint;
+            this.updateRequiredDeclarations( constraint );
+        }
+    }
+
+    /**
+     * Adds a constraint too all lists it belongs to by checking for its type 
+     * @param constraint
+     */
+    public void addConstraint(Constraint constraint) {
+        if ( constraint instanceof AlphaNodeFieldConstraint ) {
+            this.addAlphaConstraint( (AlphaNodeFieldConstraint) constraint );
+        }
+        if ( constraint instanceof BetaNodeFieldConstraint ) {
+            this.addBetaConstraint( (BetaNodeFieldConstraint) constraint );
+        }
+    }
+
+    /**
+     * Updades the cached required declaration array
+     * 
+     * @param constraint
+     */
+    protected void updateRequiredDeclarations(Constraint constraint) {
+        Declaration[] decs = constraint.getRequiredDeclarations();
+        if ( decs != null && decs.length > 0 ) {
+            for ( int i = 0; i < decs.length; i++ ) {
+                Declaration dec = decs[i];
+                // check for duplications
+                for ( int j = 0; j < this.requiredDeclarations.length; j++ ) {
+                    if ( dec.equals( this.requiredDeclarations[j] ) ) {
+                        dec = null;
+                        break;
+                    }
+                }
+                if ( dec != null ) {
+                    Declaration[] tmp = this.requiredDeclarations;
+                    this.requiredDeclarations = new Declaration[tmp.length + 1];
+                    System.arraycopy( tmp,
+                                      0,
+                                      this.requiredDeclarations,
+                                      0,
+                                      tmp.length );
+                    this.requiredDeclarations[this.requiredDeclarations.length - 1] = dec;
+                }
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Declaration[] getRequiredDeclarations() {
+        return this.requiredDeclarations;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void replaceDeclaration(Declaration oldDecl,
+                                   Declaration newDecl) {
+        for ( int i = 0; i < this.alphaConstraints.length; i++ ) {
+            this.alphaConstraints[i].replaceDeclaration( oldDecl,
+                                                         newDecl );
+        }
+        for ( int i = 0; i < this.betaConstraints.length; i++ ) {
+            this.betaConstraints[i].replaceDeclaration( oldDecl,
+                                                        newDecl );
+        }
+        for ( int i = 0; i < this.requiredDeclarations.length; i++ ) {
+            if ( this.requiredDeclarations[i] == oldDecl ) {
+                this.requiredDeclarations[i] = newDecl;
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ContextEntry getContextEntry() {
+        return new MultiFieldConstraintContextEntry( this.betaConstraints );
+    }
+
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + ArrayUtils.hashCode( this.alphaConstraints );
+        result = PRIME * result + ArrayUtils.hashCode( this.betaConstraints );
+        result = PRIME * result + ArrayUtils.hashCode( this.requiredDeclarations );
+        return result;
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+        if ( object == null || object.getClass() != AbstractCompositeConstraint.class ) {
+            return false;
+        }
+        final AbstractCompositeConstraint other = (AbstractCompositeConstraint) object;
+
+        return Arrays.equals( this.alphaConstraints,
+                              other.alphaConstraints ) && Arrays.equals( this.betaConstraints,
+                                                                         other.betaConstraints ) && Arrays.equals( this.requiredDeclarations,
+                                                                                                                   other.requiredDeclarations );
+    }
+
+    public AbstractCompositeConstraint() {
+        super();
+    }
+
+    public abstract Object clone();
+
+    /**
+     * A context entry for composite restrictions
+     * 
+     * @author etirelli
+     */
+    protected static class MultiFieldConstraintContextEntry
+        implements
+        ContextEntry {
+
+        private static final long   serialVersionUID = 400L;
+
+        public final ContextEntry[] contexts;
+        public ContextEntry         next;
+
+        public MultiFieldConstraintContextEntry(BetaNodeFieldConstraint[] constraints) {
+            contexts = new ContextEntry[constraints.length];
+            for ( int i = 0; i < contexts.length; i++ ) {
+                contexts[i] = constraints[i].getContextEntry();
+            }
+        }
+
+        public ContextEntry getNext() {
+            return this.next;
+        }
+
+        public void setNext(ContextEntry entry) {
+            this.next = entry;
+        }
+
+        public void updateFromFactHandle(InternalWorkingMemory workingMemory,
+                                         InternalFactHandle handle) {
+            for ( int i = 0; i < contexts.length; i++ ) {
+                contexts[i].updateFromFactHandle( workingMemory,
+                                                  handle );
+            }
+        }
+
+        public void updateFromTuple(InternalWorkingMemory workingMemory,
+                                    ReteTuple tuple) {
+            for ( int i = 0; i < contexts.length; i++ ) {
+                contexts[i].updateFromTuple( workingMemory,
+                                             tuple );
+            }
+        }
+        
+        public void resetTuple() {
+            for ( int i = 0, length = this.contexts.length; i < length; i++ ) {
+                this.contexts[i].resetTuple();
+            }
+        }
+        
+        public void resetFactHandle() {
+            for ( int i = 0, length = this.contexts.length; i < length; i++ ) {
+                this.contexts[i].resetFactHandle();
+            }
+        }           
+
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/AbstractCompositeRestriction.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/AbstractCompositeRestriction.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/AbstractCompositeRestriction.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,145 @@
+package org.drools.rule;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.spi.Restriction;
+
+public abstract class AbstractCompositeRestriction
+    implements
+    Restriction {
+
+    private static final long             serialVersionUID = 400L;
+
+    protected final Restriction[]         restrictions;
+    protected final CompositeContextEntry contextEntry;
+
+    public AbstractCompositeRestriction(final Restriction[] restriction) {
+        this.restrictions = restriction;
+        this.contextEntry = new CompositeContextEntry( this.restrictions );
+    }
+
+    public Declaration[] getRequiredDeclarations() {
+        // Iterate all restrictions building up a unique list of declarations
+        // No need to cache, as this should only be called once at build time
+        final Set set = new HashSet();
+        for ( int i = 0, ilength = this.restrictions.length; i < ilength; i++ ) {
+            final Declaration[] declarations = this.restrictions[i].getRequiredDeclarations();
+            for ( int j = 0, jlength = declarations.length; j < jlength; j++ ) {
+                set.add( declarations[j] );
+            }
+        }
+
+        return (Declaration[]) set.toArray( new Declaration[set.size()] );
+    }
+
+    public void replaceDeclaration(Declaration oldDecl,
+                                   Declaration newDecl) {
+        for ( int i = 0; i < this.restrictions.length; i++ ) {
+            this.restrictions[i].replaceDeclaration( oldDecl,
+                                                     newDecl );
+        }
+    }
+
+    private static int hashCode(final Object[] array) {
+        final int PRIME = 31;
+        if ( array == null ) {
+            return 0;
+        }
+        int result = 1;
+        for ( int index = 0; index < array.length; index++ ) {
+            result = PRIME * result + (array[index] == null ? 0 : array[index].hashCode());
+        }
+        return result;
+    }
+
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + AbstractCompositeRestriction.hashCode( this.restrictions );
+        return result;
+    }
+
+    public boolean equals(final Object obj) {
+        if ( this == obj ) {
+            return true;
+        }
+
+        if ( obj == null || obj instanceof AbstractCompositeRestriction ) {
+            return false;
+        }
+
+        final AbstractCompositeRestriction other = (AbstractCompositeRestriction) obj;
+        if ( !Arrays.equals( this.restrictions,
+                             other.restrictions ) ) {
+            return false;
+        }
+        return true;
+    }
+
+    public ContextEntry getContextEntry() {
+        return this.contextEntry;
+    }
+
+    public abstract Object clone();
+
+    public static class CompositeContextEntry
+        implements
+        ContextEntry {
+
+        private static final long serialVersionUID = -1773986268630111227L;
+
+        public ContextEntry[]     contextEntries;
+
+        private ContextEntry      entry;
+
+        public CompositeContextEntry(final Restriction[] restrictions) {
+            contextEntries = new ContextEntry[restrictions.length];
+            for ( int i = 0; i < restrictions.length; i++ ) {
+                contextEntries[i] = restrictions[i].getContextEntry();
+            }
+        }
+
+        public ContextEntry getNext() {
+            return this.entry;
+        }
+
+        public void setNext(final ContextEntry entry) {
+            this.entry = entry;
+        }
+
+        public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
+                                         final InternalFactHandle handle) {
+            for ( int i = 0, length = this.contextEntries.length; i < length; i++ ) {
+                this.contextEntries[i].updateFromFactHandle( workingMemory,
+                                                             handle );
+            }
+        }
+
+        public void updateFromTuple(final InternalWorkingMemory workingMemory,
+                                    final ReteTuple tuple) {
+            for ( int i = 0, length = this.contextEntries.length; i < length; i++ ) {
+                this.contextEntries[i].updateFromTuple( workingMemory,
+                                                        tuple );
+            }
+        }
+        
+        public void resetTuple() {
+            for ( int i = 0, length = this.contextEntries.length; i < length; i++ ) {
+                this.contextEntries[i].resetTuple();
+            }
+        }
+        
+        public void resetFactHandle() {
+            for ( int i = 0, length = this.contextEntries.length; i < length; i++ ) {
+                this.contextEntries[i].resetFactHandle();
+            }
+        }        
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Accumulate.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Accumulate.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Accumulate.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.rule;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.WorkingMemory;
+import org.drools.common.InternalFactHandle;
+import org.drools.spi.Accumulator;
+import org.drools.spi.Tuple;
+
+/**
+ * A class to represent the Accumulate CE
+ */
+public class Accumulate extends ConditionalElement
+    implements
+    PatternSource {
+
+    private static final long    serialVersionUID = 400L;
+
+    private Accumulator          accumulator;
+    private RuleConditionElement source;
+    private Declaration[]        requiredDeclarations;
+    private Declaration[]        innerDeclarations;
+
+    public Accumulate(final RuleConditionElement source) {
+
+        this( source,
+              new Declaration[0],
+              new Declaration[0],
+              null );
+    }
+
+    public Accumulate(final RuleConditionElement source,
+                      final Declaration[] requiredDeclarations,
+                      final Declaration[] innerDeclarations) {
+
+        this( source,
+              requiredDeclarations,
+              innerDeclarations,
+              null );
+    }
+
+    public Accumulate(final RuleConditionElement source,
+                      final Declaration[] requiredDeclarations,
+                      final Declaration[] innerDeclarations,
+                      final Accumulator accumulator) {
+
+        this.source = source;
+        this.requiredDeclarations = requiredDeclarations;
+        this.innerDeclarations = innerDeclarations;
+        this.accumulator = accumulator;
+    }
+
+    public Accumulator getAccumulator() {
+        return this.accumulator;
+    }
+
+    public void setAccumulator(final Accumulator accumulator) {
+        this.accumulator = accumulator;
+    }
+
+    public Object createContext() {
+        return this.accumulator.createContext();
+    }
+
+    /**
+     * Executes the initialization block of code
+     * 
+     * @param leftTuple tuple causing the rule fire
+     * @param declarations previous declarations
+     * @param workingMemory
+     * @throws Exception
+     */
+    public void init(final Object workingMemoryContext,
+                     final Object context,
+                     final Tuple leftTuple,
+                     final WorkingMemory workingMemory) {
+        try {
+            this.accumulator.init( workingMemoryContext,
+                                   context,
+                                   leftTuple,
+                                   this.requiredDeclarations,
+                                   workingMemory );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( e );
+        }
+    }
+
+    /**
+     * Executes the accumulate (action) code for the given fact handle
+     * 
+     * @param leftTuple
+     * @param handle
+     * @param declarations
+     * @param innerDeclarations
+     * @param workingMemory
+     * @throws Exception
+     */
+    public void accumulate(final Object workingMemoryContext,
+                           final Object context,
+                           final Tuple leftTuple,
+                           final InternalFactHandle handle,
+                           final WorkingMemory workingMemory) {
+        try {
+            this.accumulator.accumulate( workingMemoryContext,
+                                         context,
+                                         leftTuple,
+                                         handle,
+                                         this.requiredDeclarations,
+                                         this.innerDeclarations,
+                                         workingMemory );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( e );
+        }
+    }
+    
+    /**
+     * Executes the reverse (action) code for the given fact handle
+     * 
+     * @param leftTuple
+     * @param handle
+     * @param declarations
+     * @param innerDeclarations
+     * @param workingMemory
+     * @throws Exception
+     */
+    public void reverse(final Object workingMemoryContext,
+                        final Object context,
+                        final Tuple leftTuple,
+                        final InternalFactHandle handle,
+                        final WorkingMemory workingMemory) {
+        try {
+            this.accumulator.reverse( workingMemoryContext,
+                                      context,
+                                      leftTuple,
+                                      handle,
+                                      this.requiredDeclarations,
+                                      this.innerDeclarations,
+                                      workingMemory );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( e );
+        }
+    }
+    
+    /**
+     * Gets the result of the accummulation
+     * 
+     * @param leftTuple
+     * @param declarations
+     * @param workingMemory
+     * @return
+     * @throws Exception
+     */
+    public Object getResult(final Object workingMemoryContext,
+                            final Object context,
+                            final Tuple leftTuple,
+                            final WorkingMemory workingMemory) {
+        try {
+            return this.accumulator.getResult( workingMemoryContext,
+                                               context,
+                                               leftTuple,
+                                               this.requiredDeclarations,
+                                               workingMemory );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( e );
+        }
+    }
+
+    /**
+     * Returns true if this accumulate supports reverse
+     * @return
+     */
+    public boolean supportsReverse() {
+        return this.accumulator.supportsReverse();
+    }
+
+    public Object clone() {
+        return new Accumulate( this.source,
+                               this.requiredDeclarations,
+                               this.innerDeclarations,
+                               this.accumulator );
+    }
+
+    public RuleConditionElement getSource() {
+        return this.source;
+    }
+
+    public Map getInnerDeclarations() {
+        return this.source.getInnerDeclarations();
+    }
+
+    public Map getOuterDeclarations() {
+        return Collections.EMPTY_MAP;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public Declaration resolveDeclaration(final String identifier) {
+        return (Declaration) this.source.getInnerDeclarations().get( identifier );
+    }
+
+    public Object createWorkingMemoryContext() {
+        return this.accumulator.createWorkingMemoryContext();
+    }
+
+    public List getNestedElements() {
+        return Collections.singletonList( this.source );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/AndCompositeRestriction.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/AndCompositeRestriction.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/AndCompositeRestriction.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,60 @@
+package org.drools.rule;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.spi.Extractor;
+import org.drools.spi.Restriction;
+
+public class AndCompositeRestriction extends AbstractCompositeRestriction {
+
+    private static final long serialVersionUID = 400L;
+
+    public AndCompositeRestriction(final Restriction[] restriction) {
+        super( restriction );
+    }
+
+    public boolean isAllowed(final Extractor extractor,
+                             final InternalFactHandle handle,
+                             final InternalWorkingMemory workingMemory) {
+        for ( int i = 0, ilength = this.restrictions.length; i < ilength; i++ ) {
+            if ( !this.restrictions[i].isAllowed( extractor,
+                                                  handle,
+                                                  workingMemory ) ) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public boolean isAllowedCachedLeft(final ContextEntry context,
+                                       final InternalFactHandle handle) {
+        for ( int i = 0, ilength = this.restrictions.length; i < ilength; i++ ) {
+            if ( !this.restrictions[i].isAllowedCachedLeft( this.contextEntry.contextEntries[i],
+                                                            handle ) ) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public boolean isAllowedCachedRight(final ReteTuple tuple,
+                                        final ContextEntry context) {
+        for ( int i = 0, ilength = this.restrictions.length; i < ilength; i++ ) {
+            if ( !this.restrictions[i].isAllowedCachedRight( tuple,
+                                                             this.contextEntry.contextEntries[i] ) ) {
+                return false;
+            }
+        }
+        return true;
+    }
+    
+    public Object clone() {
+        Restriction[] clone = new Restriction[ this.restrictions.length ];
+        for( int i = 0; i < clone.length; i++ ) {
+            clone[i] = (Restriction) this.restrictions[i].clone();
+        }
+        return new AndCompositeRestriction( clone );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/AndConstraint.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/AndConstraint.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/AndConstraint.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2006 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.
+ *
+ * Created on May 14, 2007
+ */
+package org.drools.rule;
+
+import java.util.Arrays;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.util.ArrayUtils;
+
+/**
+ * AND composite constraint, so the user can do things like:
+ * 
+ * Person( name == 'Edson' && surname == 'Tirelli' )
+ * 
+ * @author etirelli
+ *
+ */
+public class AndConstraint extends AbstractCompositeConstraint {
+
+    private static final long serialVersionUID = 400L;
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isAllowed(InternalFactHandle handle,
+                             InternalWorkingMemory workingMemory) {
+        if ( this.alphaConstraints.length > 0 ) {
+            for ( int i = 0; i < this.alphaConstraints.length; i++ ) {
+                if ( !this.alphaConstraints[i].isAllowed( handle,
+                                                          workingMemory ) ) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isAllowedCachedLeft(ContextEntry context,
+                                       InternalFactHandle handle) {
+        if ( this.betaConstraints.length > 0 ) {
+            for ( int i = 0; i < this.betaConstraints.length; i++ ) {
+                if ( !this.betaConstraints[i].isAllowedCachedLeft( ((MultiFieldConstraintContextEntry)context).contexts[i],
+                                                                   handle ) ) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isAllowedCachedRight(ReteTuple tuple,
+                                        ContextEntry context) {
+        if ( this.betaConstraints.length > 0 ) {
+            for ( int i = 0; i < this.betaConstraints.length; i++ ) {
+                if ( !this.betaConstraints[i].isAllowedCachedRight( tuple,
+                                                                    ((MultiFieldConstraintContextEntry)context).contexts[i] ) ) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+    
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + ArrayUtils.hashCode( this.alphaConstraints );
+        result = PRIME * result + ArrayUtils.hashCode( this.betaConstraints );
+        result = PRIME * result + ArrayUtils.hashCode( this.requiredDeclarations );
+        return result;
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+        if ( object == null || object.getClass() != AndConstraint.class ) {
+            return false;
+        }
+        final AndConstraint other = (AndConstraint) object;
+
+        return Arrays.equals( this.alphaConstraints,
+                              other.alphaConstraints ) && Arrays.equals( this.betaConstraints,
+                                                                         other.betaConstraints ) && Arrays.equals( this.requiredDeclarations,
+                                                                                                                   other.requiredDeclarations );
+    }
+    
+    public Object clone() {
+        AndConstraint clone = new AndConstraint();
+        
+        // clone alpha constraints
+        clone.alphaConstraints = new AlphaNodeFieldConstraint[ this.alphaConstraints.length ];
+        for( int i = 0; i < this.alphaConstraints.length; i++ ) {
+            clone.alphaConstraints[i] = (AlphaNodeFieldConstraint) this.alphaConstraints[i].clone();
+            clone.updateRequiredDeclarations( clone.alphaConstraints[i] );
+        }
+        
+        // clone beta constraints
+        clone.betaConstraints = new BetaNodeFieldConstraint[ this.betaConstraints.length ];
+        for( int i = 0; i < this.betaConstraints.length; i++ ) {
+            clone.betaConstraints[i] = (BetaNodeFieldConstraint) this.betaConstraints[i].clone();
+            clone.updateRequiredDeclarations( clone.betaConstraints[i] );
+        }
+        
+        return clone;
+    }
+    
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Collect.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Collect.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Collect.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.rule;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.ClassObjectType;
+
+/**
+ * @author etirelli
+ *
+ */
+public class Collect extends ConditionalElement
+    implements
+    PatternSource {
+
+    private static final long serialVersionUID = 400L;
+
+    private Pattern           sourcePattern;
+    private Pattern           resultPattern;
+
+    public Collect(final Pattern sourcePattern,
+                   final Pattern resultPattern) {
+
+        this.sourcePattern = sourcePattern;
+        this.resultPattern = resultPattern;
+    }
+
+    public Object clone() {
+        return new Collect( this.sourcePattern,
+                            this.resultPattern );
+    }
+
+    public Pattern getResultPattern() {
+        return this.resultPattern;
+    }
+
+    public Pattern getSourcePattern() {
+        return this.sourcePattern;
+    }
+
+    public Collection instantiateResultObject() throws RuntimeDroolsException {
+        try {
+            // Collect can only be used with a Collection implementation, so
+            // FactTemplateObject type is not allowed
+            return (Collection) ((ClassObjectType) this.resultPattern.getObjectType()).getClassType().newInstance();
+        } catch ( final ClassCastException cce ) {
+            throw new RuntimeDroolsException( "Collect CE requires a Collection implementation as return type",
+                                              cce );
+        } catch ( final InstantiationException e ) {
+            throw new RuntimeDroolsException( "Collect CE requires a non-argument constructor for the return type",
+                                              e );
+        } catch ( final IllegalAccessException e ) {
+            throw new RuntimeDroolsException( "Collect CE requires an accessible constructor for the return type",
+                                              e );
+        }
+    }
+
+    public Map getInnerDeclarations() {
+        return this.sourcePattern.getInnerDeclarations();
+    }
+
+    public Map getOuterDeclarations() {
+        return Collections.EMPTY_MAP;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public Declaration resolveDeclaration(final String identifier) {
+        return (Declaration) this.sourcePattern.getInnerDeclarations().get( identifier );
+    }
+
+    public List getNestedElements() {
+        return Collections.singletonList( this.sourcePattern );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/CompositePackageClassLoader.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/CompositePackageClassLoader.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/CompositePackageClassLoader.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,79 @@
+package org.drools.rule;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class CompositePackageClassLoader extends ClassLoader {
+
+    private final List classLoaders = new ArrayList();
+
+    public CompositePackageClassLoader(final ClassLoader parentClassLoader) {
+        super( parentClassLoader );
+    }
+
+    public void addClassLoader(final ClassLoader classLoader) {
+        this.classLoaders.add( classLoader );
+    }
+
+    public void removeClassLoader(final ClassLoader classLoader) {
+        for ( final Iterator it = this.classLoaders.iterator(); it.hasNext(); ) {
+            if ( it.next() == classLoader ) {
+                it.remove();
+                break;
+            }
+        }
+    }
+
+    private Class compositeFastFindClass(final String name) {
+        for ( final Iterator it = this.classLoaders.iterator(); it.hasNext(); ) {
+            final DroolsClassLoader classLoader = (DroolsClassLoader) it.next();
+            final Class clazz = classLoader.fastFindClass( name );
+            if ( clazz != null ) {
+                return clazz;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Javadocs recommend that this method not be overloaded. We overload this so that we can prioritise the fastFindClass 
+     * over method calls to parent.loadClass(name, false); and c = findBootstrapClass0(name); which the default implementation
+     * would first - hence why we call it "fastFindClass" instead of standard findClass, this indicates that we give it a 
+     * higher priority than normal.
+     * 
+     */
+    protected synchronized Class loadClass(final String name,
+                                           final boolean resolve) throws ClassNotFoundException {
+        Class clazz = findLoadedClass( name );
+
+        if ( clazz == null ) {
+            clazz = compositeFastFindClass( name );
+
+            if ( clazz == null ) {
+
+                final ClassLoader parent = getParent();
+                if ( parent != null ) {
+                    clazz = parent.loadClass( name );
+                } else {
+                    throw new ClassNotFoundException( name );
+                }
+            }
+        }
+
+        if ( resolve ) {
+            resolveClass( clazz );
+        }
+
+        return clazz;
+    }
+
+    protected Class findClass(final String name) throws ClassNotFoundException {
+        final Class clazz = compositeFastFindClass( name );
+        if ( clazz == null ) {
+            throw new ClassNotFoundException( name );
+        }
+        return clazz;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/ConditionalElement.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/ConditionalElement.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/ConditionalElement.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,25 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public abstract class ConditionalElement
+    implements
+    RuleConditionElement {
+
+    public abstract Object clone();
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/ContextEntry.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/ContextEntry.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/ContextEntry.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,27 @@
+package org.drools.rule;
+
+import java.io.Serializable;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.ReteTuple;
+
+public interface ContextEntry
+    extends
+    Serializable {
+
+    public ContextEntry getNext();
+
+    public void setNext(ContextEntry entry);
+
+    public void updateFromTuple(InternalWorkingMemory workingMemory,
+                                ReteTuple tuple);
+
+    public void updateFromFactHandle(InternalWorkingMemory workingMemory,
+                                     InternalFactHandle handle);
+    
+    public void resetTuple();
+    
+    public void resetFactHandle();
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Declaration.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Declaration.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Declaration.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,331 @@
+package org.drools.rule;
+
+/*
+ * $Id: Declaration.java,v 1.1 2005/07/26 01:06:31 mproctor Exp $
+ *
+ * Copyright 2001-2003 (C) The Werken Company. All Rights Reserved.
+ *
+ * Redistribution and use of this software and associated documentation
+ * ("Software"), with or without modification, are permitted provided that the
+ * following conditions are met:
+ *
+ * 1. Redistributions of source code must retain copyright statements and
+ * notices. Redistributions must also contain a copy of this document.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name "drools" must not be used to endorse or promote products derived
+ * from this Software without prior written permission of The Werken Company.
+ * For written permission, please contact bob at werken.com.
+ *
+ * 4. Products derived from this Software may not be called "drools" nor may
+ * "drools" appear in their names without prior written permission of The Werken
+ * Company. "drools" is a trademark of The Werken Company.
+ *
+ * 5. Due credit should be given to The Werken Company. (http://werken.com/)
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE WERKEN COMPANY AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE WERKEN COMPANY OR ITS CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.ShadowProxy;
+import org.drools.base.ValueType;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.Extractor;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris </a>
+ *
+ */
+public class Declaration
+    implements
+    Serializable,
+    Cloneable {
+    // ------------------------------------------------------------
+    // Instance members
+    // ------------------------------------------------------------
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    /** The identifier for the variable. */
+    private final String      identifier;
+
+    private final Extractor   extractor;
+
+    private Pattern           pattern;
+
+    private final boolean     internalFact;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    /**
+     * Construct.
+     * 
+     * @param identifier
+     *            The name of the variable.
+     * @param objectType
+     *            The type of this variable declaration.
+     * @param order
+     *            The index within a rule.
+     */
+    public Declaration(final String identifier,
+                       final Extractor extractor,
+                       final Pattern pattern) {
+        this( identifier,
+              extractor,
+              pattern,
+              false );
+    }
+
+    /**
+     * Construct.
+     * 
+     * @param identifier
+     *            The name of the variable.
+     * @param objectType
+     *            The type of this variable declaration.
+     * @param order
+     *            The index within a rule.
+     * @param internalFact
+     *            True if this is an internal fact created by the engine, like a collection result
+     *            of a collect CE
+     */
+    public Declaration(final String identifier,
+                       final Extractor extractor,
+                       final Pattern pattern,
+                       final boolean internalFact) {
+        this.identifier = identifier;
+        this.extractor = extractor;
+        this.pattern = pattern;
+        this.internalFact = internalFact;
+    }
+
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+
+    /**
+     * Retrieve the variable's identifier.
+     * 
+     * @return The variable's identifier.
+     */
+    public String getIdentifier() {
+        return this.identifier;
+    }
+
+    /**
+     * Retrieve the <code>ValueType</code>.
+     * 
+     * @return The ValueType.
+     */
+    public ValueType getValueType() {
+        return this.extractor.getValueType();
+    }
+
+    /**
+     * Returns the index of the pattern
+     * 
+     * @return the pattern
+     */
+    public Pattern getPattern() {
+        return this.pattern;
+    }
+
+    public void setPattern(final Pattern pattern) {
+        this.pattern = pattern;
+    }
+
+    /**
+     * Returns true if this declaration is a pattern declaration
+     * @return
+     */
+    public boolean isPatternDeclaration() {
+        return this.pattern != null && this.pattern.getDeclaration() == this;
+    }
+
+    /**
+     * Returns the Extractor expression
+     * 
+     * @return
+     */
+    public Extractor getExtractor() {
+        return this.extractor;
+    }
+
+    public Object getValue(InternalWorkingMemory workingMemory,
+                           final Object object) {
+        return this.extractor.getValue( workingMemory,
+                                        object );
+    }
+
+    public Object getNonShadowedValue(InternalWorkingMemory workingMemory,
+                                      final Object object) {
+        Object result = this.extractor.getValue( workingMemory,
+                                                 object );
+        if ( this.isInternalFact() && result instanceof Collection ) {
+            try {
+                Collection newCol = (Collection) result.getClass().newInstance();
+                for ( Iterator it = ((Collection) result).iterator(); it.hasNext(); ) {
+                    Object element = it.next();
+                    newCol.add( (element instanceof ShadowProxy) ? ((ShadowProxy) element).getShadowedObject() : element );
+                }
+                return newCol;
+            } catch ( InstantiationException e ) {
+                // nothing we can do, so just return the resulting object
+            } catch ( IllegalAccessException e ) {
+                // TODO Auto-generated catch block
+            }
+        }
+        return result;
+    }
+
+    public char getCharValue(InternalWorkingMemory workingMemory,
+                             final Object object) {
+        return this.extractor.getCharValue( workingMemory,
+                                            object );
+    }
+
+    public int getIntValue(InternalWorkingMemory workingMemory,
+                           final Object object) {
+        return this.extractor.getIntValue( workingMemory,
+                                           object );
+    }
+
+    public byte getByteValue(InternalWorkingMemory workingMemory,
+                             final Object object) {
+        return this.extractor.getByteValue( workingMemory,
+                                            object );
+    }
+
+    public short getShortValue(InternalWorkingMemory workingMemory,
+                               final Object object) {
+        return this.extractor.getShortValue( workingMemory,
+                                             object );
+    }
+
+    public long getLongValue(InternalWorkingMemory workingMemory,
+                             final Object object) {
+        return this.extractor.getLongValue( workingMemory,
+                                            object );
+    }
+
+    public float getFloatValue(InternalWorkingMemory workingMemory,
+                               final Object object) {
+        return this.extractor.getFloatValue( workingMemory,
+                                             object );
+    }
+
+    public double getDoubleValue(InternalWorkingMemory workingMemory,
+                                 final Object object) {
+        return this.extractor.getDoubleValue( workingMemory,
+                                              object );
+    }
+
+    public boolean getBooleanValue(InternalWorkingMemory workingMemory,
+                                   final Object object) {
+        return this.extractor.getBooleanValue( workingMemory,
+                                               object );
+    }
+
+    public int getHashCode(InternalWorkingMemory workingMemory,
+                           final Object object) {
+        return this.extractor.getHashCode( workingMemory,
+                                           object );
+    }
+
+    public boolean isGlobal() {
+        return this.extractor.isGlobal();
+    }
+
+    public Method getNativeReadMethod() {
+        if ( this.isPatternDeclaration() && this.isInternalFact() ) {
+            try {
+                return this.getClass().getDeclaredMethod( "getNonShadowedValue",
+                                                          new Class[]{InternalWorkingMemory.class, Object.class} );
+            } catch ( final Exception e ) {
+                throw new RuntimeDroolsException( "This is a bug. Please report to development team: " + e.getMessage(),
+                                                  e );
+            }
+        } 
+        return this.extractor.getNativeReadMethod();
+    }
+
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+    public String toString() {
+        return "[Declaration: type=" + this.extractor.getValueType() + " identifier=" + this.identifier + "]";
+    }
+
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * this.pattern.getOffset();
+        result = PRIME * this.extractor.hashCode();
+        result = PRIME * this.identifier.hashCode();
+        return result;
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || getClass() != object.getClass() ) {
+            return false;
+        }
+
+        final Declaration other = (Declaration) object;
+
+        return this.pattern.getOffset() == other.pattern.getOffset() && this.identifier.equals( other.identifier ) && this.extractor.equals( other.extractor );
+    }
+
+    protected boolean isInternalFact() {
+        return internalFact;
+    }
+    
+    public Object clone() {
+        return new Declaration( this.identifier, this.extractor, this.pattern );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Dialectable.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Dialectable.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Dialectable.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,5 @@
+package org.drools.rule;
+
+public interface Dialectable {
+    public String getDialect();
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/DroolsClassLoader.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/DroolsClassLoader.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/DroolsClassLoader.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,5 @@
+package org.drools.rule;
+
+public interface DroolsClassLoader {
+    public Class fastFindClass(final String name);
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/DuplicateRuleNameException.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/DuplicateRuleNameException.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/DuplicateRuleNameException.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,116 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Indicates an attempt to add a <code>Rule</code> to a <code>Package</code>
+ * that already contains a <code>Rule</code> with the same name.
+ * 
+ * @see Rule
+ * @see Package
+ * 
+ * @author <a href="mailto:bob at eng.werken.com">bob mcwhirter </a>
+ */
+public class DuplicateRuleNameException extends RuleConstructionException {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    /** The rule-set. */
+    private Package           pkg;
+
+    /** The member rule. */
+    private Rule              originalRule;
+
+    /** The conflicting rule. */
+    private Rule              conflictingRule;
+
+    /**
+     * @see java.lang.Exception#Exception()
+     * 
+     * @param pkg
+     *            The <code>Package</code>.
+     * @param originalRule
+     *            The <code>Rule</code> already in the <code>Package</code>.
+     * @param conflictingRule
+     *            The new, conflicting <code>Rule</code>.
+     */
+    public DuplicateRuleNameException(final Package pkg,
+                                      final Rule originalRule,
+                                      final Rule conflictingRule) {
+        super( createMessage( pkg,
+                              conflictingRule ) );
+        this.pkg = pkg;
+        this.originalRule = originalRule;
+        this.conflictingRule = conflictingRule;
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(Throwable cause)
+     * 
+     * @param pkg
+     *            The <code>Package</code>.
+     * @param originalRule
+     *            The <code>Rule</code> already in the <code>Package</code>.
+     * @param conflictingRule
+     *            The new, conflicting <code>Rule</code>.
+     */
+    public DuplicateRuleNameException(final Package pkg,
+                                      final Rule originalRule,
+                                      final Rule conflictingRule,
+                                      final Throwable cause) {
+        super( createMessage( pkg,
+                              conflictingRule ),
+               cause );
+        this.pkg = pkg;
+        this.originalRule = originalRule;
+        this.conflictingRule = conflictingRule;
+    }
+
+    /**
+     * Retrieve the <code>Package</code>.
+     * 
+     * @return The <code>Package</code>.
+     */
+    public Package getPackage() {
+        return this.pkg;
+    }
+
+    /**
+     * Retrieve the original <code>Rule</code> in the <code>Package</code>.
+     * 
+     * @return The <code>Rule</code>.
+     */
+    public Rule getOriginalRule() {
+        return this.originalRule;
+    }
+
+    /**
+     * Retrieve the new conflicting <code>Rule</code>.
+     * 
+     * @return The <code>Rule</code>.
+     */
+    public Rule getConflictingRule() {
+        return this.conflictingRule;
+    }
+
+    private static String createMessage(final Package pkg,
+                                        final Rule rule) {
+        return "Package " + ((pkg.getName() != null) ? pkg.getName() : "<no-name>") + " already contains rule with name " + rule.getName();
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/EntryPoint.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/EntryPoint.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/EntryPoint.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 14, 2007
+ */
+package org.drools.rule;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class defines a Rete "Entry Point".
+ * An entry point is used as a source of facts that
+ * are scoped to a separate alpha network. The alpha
+ * network is not shared among separate entry points
+ * and this allows them to safelly run in parallel
+ * and concurrent modes.
+ * 
+ * @author etirelli
+ *
+ */
+public class EntryPoint extends ConditionalElement
+    implements
+    PatternSource {
+
+    public static final EntryPoint DEFAULT = new EntryPoint("DEFAULT");
+    
+    private static final long serialVersionUID = 1435985794248365232L;
+    
+    private final String entryPointId;
+    
+    /**
+     * Constructor.
+     * 
+     * @param entryPointId the ID for this entry point
+     */
+    public EntryPoint( final String entryPointId ) {
+        this.entryPointId = entryPointId;
+    }
+
+    /** 
+     * There is not reason to clone this object since it is stateless. 
+     * So a clone() call will return the instance itself.
+     *  
+     * @see org.drools.rule.ConditionalElement#clone()
+     */
+    @Override
+    public Object clone() {
+        return this;
+    }
+
+    /** 
+     * It is not possible to declare any new variables, so always
+     * return an Empty Map
+     * 
+     * @see org.drools.rule.RuleConditionElement#getInnerDeclarations()
+     */
+    public Map getInnerDeclarations() {
+        return Collections.EMPTY_MAP;
+    }
+
+    /**
+     * It is not possible to nest elements inside an entry point, so
+     * always return an empty list.
+     * 
+     * @see org.drools.rule.RuleConditionElement#getNestedElements()
+     */
+    public List getNestedElements() {
+        return Collections.EMPTY_LIST;
+    }
+
+    /**
+     * It is not possible to declare and export any variables,
+     * so always return an empty map
+     * 
+     * @see org.drools.rule.RuleConditionElement#getOuterDeclarations()
+     */
+    public Map getOuterDeclarations() {
+        return Collections.EMPTY_MAP;
+    }
+
+    /** 
+     * Not possible to resolve any declaration, so always return null.
+     * 
+     * @see org.drools.rule.RuleConditionElement#resolveDeclaration(java.lang.String)
+     */
+    public Declaration resolveDeclaration(String identifier) {
+        return null;
+    }
+    
+    /**
+     * Returns this entry point ID
+     * @return
+     */
+    public String getEntryPointId() {
+        return this.entryPointId;
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + ((entryPointId == null) ? 0 : entryPointId.hashCode());
+        return result;
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if ( this == obj ) return true;
+        if ( obj == null ) return false;
+        if ( getClass() != obj.getClass() ) return false;
+        final EntryPoint other = (EntryPoint) obj;
+        if ( entryPointId == null ) {
+            if ( other.entryPointId != null ) return false;
+        } else if ( !entryPointId.equals( other.entryPointId ) ) return false;
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "EntryPoint::"+this.entryPointId;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/EvalCondition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/EvalCondition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/EvalCondition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,137 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.WorkingMemory;
+import org.drools.spi.EvalExpression;
+import org.drools.spi.Tuple;
+
+public class EvalCondition extends ConditionalElement {
+    /**
+     * 
+     */
+    private static final long          serialVersionUID = 400L;
+
+    private EvalExpression             expression;
+
+    private final Declaration[]        requiredDeclarations;
+
+    private static final Declaration[] EMPTY_DECLARATIONS = new Declaration[0];
+
+    public EvalCondition(final Declaration[] requiredDeclarations) {
+        this( null,
+              requiredDeclarations );
+    }
+
+    public EvalCondition(final EvalExpression eval,
+                         final Declaration[] requiredDeclarations) {
+
+        this.expression = eval;
+
+        if ( requiredDeclarations == null ) {
+            this.requiredDeclarations = EvalCondition.EMPTY_DECLARATIONS;
+        } else {
+            this.requiredDeclarations = requiredDeclarations;
+        }
+    }
+
+    public EvalExpression getEvalExpression() {
+        return this.expression;
+    }
+
+    public void setEvalExpression(final EvalExpression expression) {
+        this.expression = expression;
+    }
+
+    public Declaration[] getRequiredDeclarations() {
+        return this.requiredDeclarations;
+    }
+
+    public boolean isAllowed(final Tuple tuple,
+                             final WorkingMemory workingMemory) {
+        try {
+            return this.expression.evaluate( tuple,
+                                             this.requiredDeclarations,
+                                             workingMemory );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( e );
+        }
+    }
+
+    public Object clone() {
+        final EvalCondition eval = new EvalCondition( this.expression,
+                                                      this.requiredDeclarations );
+        return eval;
+    }
+
+    public int hashCode() {
+        return this.expression.hashCode();
+    }
+
+    public boolean equals(final Object object) {
+        if ( object == this ) {
+            return true;
+        }
+
+        if ( object == null || object.getClass() != EvalCondition.class ) {
+            return false;
+        }
+
+        final EvalCondition other = (EvalCondition) object;
+
+        if ( this.requiredDeclarations.length != other.requiredDeclarations.length ) {
+            return false;
+        }
+
+        for ( int i = 0, length = this.requiredDeclarations.length; i < length; i++ ) {
+            if ( this.requiredDeclarations[i].getPattern().getOffset() != other.requiredDeclarations[i].getPattern().getOffset() ) {
+                return false;
+            }
+
+            if ( !this.requiredDeclarations[i].getExtractor().equals( other.requiredDeclarations[i].getExtractor() ) ) {
+                return false;
+            }
+        }
+
+        return this.expression.equals( other.expression );
+    }
+
+    public Map getInnerDeclarations() {
+        return Collections.EMPTY_MAP;
+    }
+
+    public Map getOuterDeclarations() {
+        return Collections.EMPTY_MAP;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public Declaration resolveDeclaration(final String identifier) {
+        return null;
+    }
+
+    public List getNestedElements() {
+        return Collections.EMPTY_LIST;
+    }
+
+};
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/FixedDuration.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/FixedDuration.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/FixedDuration.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,129 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.Duration;
+import org.drools.spi.Tuple;
+
+/**
+ * A fixed truthness duration.
+ * 
+ * @see Rule#setDuration
+ * @see Rule#getDuration
+ * 
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter </a>
+ * 
+ * @version $Id: FixedDuration.java,v 1.2 2005/08/14 22:34:41 mproctor Exp $
+ */
+public class FixedDuration
+    implements
+    Duration {
+    // ------------------------------------------------------------
+    // Instance members
+    // ------------------------------------------------------------
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+    /** Duration, in seconds. */
+    private long              duration;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    /**
+     * Construct.
+     */
+    public FixedDuration() {
+        this.duration = 0;
+    }
+
+    /**
+     * Construct.
+     * 
+     * @param seconds
+     *            Number of seconds.
+     */
+    public FixedDuration(final long ms) {
+        this.duration = ms;
+    }
+
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+
+    /**
+     * Add seconds.
+     * 
+     * @param seconds
+     *            Number of seconds.
+     */
+    public void addSeconds(final long seconds) {
+        this.duration += (seconds * 1000);
+    }
+
+    /**
+     * Add minutes.
+     * 
+     * @param minutes
+     *            Number of minutes.
+     */
+    public void addMinutes(final long minutes) {
+        this.duration += ((minutes * 60) * 1000);
+    }
+
+    /**
+     * Add hours.
+     * 
+     * @param hours
+     *            Number of hours.
+     */
+    public void addHours(final long hours) {
+        this.duration += ((hours * 60 * 60) * 1000);
+    }
+
+    /**
+     * Add days.
+     * 
+     * @param days
+     *            Number of days.
+     */
+    public void addDays(final long days) {
+        this.duration += ((days * 60 * 60 * 24) * 1000);
+    }
+
+    /**
+     * Add weeks.
+     * 
+     * @param weeks
+     *            Number of weeks.
+     */
+    public void addWeeks(final long weeks) {
+        this.duration += ((weeks * 60 * 60 * 24 * 7) * 1000);
+    }
+
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+    /**
+     * @see Duration
+     */
+    public long getDuration(final Tuple tuple) {
+        return this.duration;
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Forall.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Forall.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Forall.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2006 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.rule;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * The forall conditional element.
+ * 
+ * @author etirelli
+ */
+public class Forall extends ConditionalElement {
+
+    private static final long serialVersionUID = 400L;
+
+    // forall base pattern
+    private Pattern            basePattern;
+    // foral remaining patterns
+    private List              remainingPatterns;
+
+    public Forall() {
+        this( null,
+              new ArrayList( 1 ) );
+    }
+
+    public Forall(final Pattern basePattern) {
+        this( basePattern,
+              new ArrayList( 1 ) );
+    }
+
+    public Forall(final Pattern basePattern,
+                  final List remainingPatterns) {
+        this.basePattern = basePattern;
+        this.remainingPatterns = remainingPatterns;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.rule.ConditionalElement#clone()
+     */
+    public Object clone() {
+        return new Forall( this.basePattern,
+                           new ArrayList( this.remainingPatterns ) );
+    }
+
+    /**
+     * Forall inner declarations are only provided by the base patterns
+     * since it negates the remaining patterns
+     */
+    public Map getInnerDeclarations() {
+        final Map inner = new HashMap( this.basePattern.getOuterDeclarations() );
+        for ( final Iterator it = this.remainingPatterns.iterator(); it.hasNext(); ) {
+            inner.putAll( ((Pattern) it.next()).getOuterDeclarations() );
+        }
+        return inner;
+    }
+
+    /**
+     * Forall does not export any declarations
+     */
+    public Map getOuterDeclarations() {
+        return Collections.EMPTY_MAP;
+    }
+
+    /**
+     * Forall can only resolve declarations from its base pattern
+     */
+    public Declaration resolveDeclaration(final String identifier) {
+        return (Declaration) this.getInnerDeclarations().get( identifier );
+    }
+
+    /**
+     * @return the basePattern
+     */
+    public Pattern getBasePattern() {
+        return this.basePattern;
+    }
+
+    /**
+     * @param basePattern the basePattern to set
+     */
+    public void setBasePattern(final Pattern basePattern) {
+        this.basePattern = basePattern;
+    }
+
+    /**
+     * @return the remainingPatterns
+     */
+    public List getRemainingPatterns() {
+        return this.remainingPatterns;
+    }
+
+    /**
+     * @param remainingPatterns the remainingPatterns to set
+     */
+    public void setRemainingPatterns(final List remainingPatterns) {
+        this.remainingPatterns = remainingPatterns;
+    }
+
+    /**
+     * Adds one more pattern to the list of remaining patterns
+     * @param pattern
+     */
+    public void addRemainingPattern(final Pattern pattern) {
+        this.remainingPatterns.add( pattern );
+    }
+
+    public List getNestedElements() {
+        List elements = new ArrayList( 1 + this.remainingPatterns.size() );
+        elements.add( this.basePattern );
+        elements.addAll( this.remainingPatterns );
+        return elements;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/From.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/From.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/From.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,51 @@
+package org.drools.rule;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.spi.DataProvider;
+
+public class From extends ConditionalElement
+    implements
+    Serializable,
+    PatternSource {
+
+    private static final long serialVersionUID = 400L;
+
+    private DataProvider      dataProvider;
+
+    public From(final DataProvider dataProvider) {
+        this.dataProvider = dataProvider;
+    }
+
+    public DataProvider getDataProvider() {
+        return this.dataProvider;
+    }
+
+    public Object clone() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Map getInnerDeclarations() {
+        return Collections.EMPTY_MAP;
+    }
+
+    public Map getOuterDeclarations() {
+        return Collections.EMPTY_MAP;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public Declaration resolveDeclaration(final String identifier) {
+        return null;
+    }
+    
+    public List getNestedElements() {
+        return Collections.EMPTY_LIST;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/GroupElement.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/GroupElement.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/GroupElement.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,573 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+
+public class GroupElement extends ConditionalElement {
+
+    private static final long serialVersionUID = 400L;
+
+    public static final Type  AND              = new AndType();
+    public static final Type  OR               = new OrType();
+    public static final Type  EXISTS           = new ExistsType();
+    public static final Type  NOT              = new NotType();
+
+    private Type              type             = null;
+    private final List        children         = new ArrayList();
+
+    public GroupElement() {
+        this( AND );
+    }
+
+    public GroupElement(final Type type) {
+        this.type = type;
+    }
+
+    /**
+     * Adds a child to the current GroupElement.
+     * 
+     * Restrictions are:
+     * NOT/EXISTS: can have only one child, either a single Pattern or another CE
+     * 
+     * @param child
+     */
+    public void addChild(final RuleConditionElement child) {
+        if ( (this.isNot() || this.isExists()) && (this.children.size() > 0) ) {
+            throw new RuntimeDroolsException( this.type.toString() + " can have only a single child element. Either a single Pattern or another CE." );
+        }
+        this.children.add( child );
+    }
+
+    /**
+     * Adds the given child as the (index)th child of the this GroupElement 
+     * @param index
+     * @param rce
+     */
+    public void addChild(final int index,
+                         final RuleConditionElement rce) {
+        this.children.add( index,
+                           rce );
+    }
+
+    public List getChildren() {
+        return this.children;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public Map getInnerDeclarations() {
+        return this.type.getInnerDeclarations( this.children );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public Map getOuterDeclarations() {
+        return this.type.getOuterDeclarations( this.children );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public Declaration resolveDeclaration(final String identifier) {
+        return (Declaration) this.type.getInnerDeclarations( this.children ).get( identifier );
+    }
+
+    /**
+     * Optimize the group element subtree by removing redundancies
+     * like an AND inside another AND, OR inside OR, single branches
+     * AND/OR, etc.
+     * 
+     * LogicTransformer does further, more complicated, transformations
+     */
+    public void pack() {
+        // we must clone, since we want to iterate only over the original list
+        final Object[] clone = this.children.toArray();
+        for ( int i = 0; i < clone.length; i++ ) {
+            // if child is also a group element, there may be 
+            // some possible clean up / optimizations to be done
+            if ( clone[i] instanceof GroupElement ) {
+                final GroupElement childGroup = (GroupElement) clone[i];
+                childGroup.pack( this );
+            }
+        }
+
+        // if after packing, this is an AND or OR GE with a single
+        // child GE, then clone child into current node eliminating child
+        if ( (this.isAnd() || this.isOr()) && (this.children.size() == 1) ) {
+            final Object child = this.getChildren().get( 0 );
+            if ( child instanceof GroupElement ) {
+                final GroupElement group = (GroupElement) child;
+                this.type = group.getType();
+                this.children.clear();
+                this.children.addAll( group.getChildren() );
+            }
+        }
+        
+    }
+
+    /**
+     * @param parent
+     */
+    public void pack(final GroupElement parent) {
+        if ( this.children.size() == 0 ) {
+            // if there is no child, just remove this node
+            parent.children.remove( this );
+            return;
+        }
+
+        // If this is  an AND or OR or EXISTS, there are some possible merges
+        if ( this.isAnd() || this.isOr() || this.isExists() ) {
+
+            // if parent is of the same type as current node,
+            // then merge this childs with parent childs
+            if ( parent.getType() == this.getType() ) {
+
+                // we must keep the order so, save index
+                int index = parent.getChildren().indexOf( this );
+                parent.getChildren().remove( this );
+                // for each child, pack it and add it to parent
+                for ( final Iterator childIt = this.children.iterator(); childIt.hasNext(); ) {
+                    final Object child = childIt.next();
+                    // we must keep the order, so add in the same place were parent was before
+                    parent.getChildren().add( index++,
+                                              child );
+                    if ( child instanceof GroupElement ) {
+                        final int previousSize = parent.getChildren().size();
+                        ((GroupElement) child).pack( parent );
+                        // in case the child also added elements to the parent, 
+                        // we need to compensate
+                        index += (parent.getChildren().size() - previousSize);
+                    }
+                }
+
+                // if current node has a single child, then move it to parent and pack it
+            } else if ( (!this.isExists()) && (this.children.size() == 1) ) {
+                // we must keep the order so, save index
+                final int index = parent.getChildren().indexOf( this );
+                parent.getChildren().remove( this );
+
+                final Object child = this.children.get( 0 );
+                parent.getChildren().add( index,
+                                          child );
+
+                if ( child instanceof GroupElement ) {
+                    ((GroupElement) child).pack( parent );
+                }
+
+                // otherwise pack itself
+            } else {
+                this.pack();
+            }
+
+            // also pack itself if it is a NOT 
+        } else {
+            this.pack();
+        }
+    }
+
+    /**
+     * Traverses two trees and checks that they are structurally equal at all
+     * levels
+     * 
+     * @param e1
+     * @param e2
+     * @return
+     */
+    public boolean equals(final Object object) {
+        // Return false if its null or not an instance of ConditionalElement
+        if ( object == null || !(object instanceof GroupElement) ) {
+            return false;
+        }
+
+        // Return true if they are the same reference
+        if ( this == object ) {
+            return true;
+        }
+
+        // Now try a recurse manual check
+        final GroupElement e2 = (GroupElement) object;
+        if ( !this.type.equals( e2.type ) ) {
+            return false;
+        }
+
+        final List e1Children = this.getChildren();
+        final List e2Children = e2.getChildren();
+        if ( e1Children.size() != e2Children.size() ) {
+            return false;
+        }
+
+        for ( int i = 0; i < e1Children.size(); i++ ) {
+            final Object e1Object1 = e1Children.get( i );
+            final Object e2Object1 = e2Children.get( i );
+            if ( !e1Object1.equals( e2Object1 ) ) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    public int hashCode() {
+        return this.type.hashCode() + this.children.hashCode();
+    }
+
+    /**
+     * Clones all Conditional Elements but references the non ConditionalElement
+     * children
+     * 
+     * @param e1
+     * @param e2
+     * @return
+     */
+    public Object clone() {
+        GroupElement cloned = null;
+
+        try {
+            cloned = (GroupElement) this.getClass().newInstance();
+        } catch ( final InstantiationException e ) {
+            throw new RuntimeException( "Could not clone '" + this.getClass().getName() + "'" );
+        } catch ( final IllegalAccessException e ) {
+            throw new RuntimeException( "Could not clone '" + this.getClass().getName() + "'" );
+        }
+
+        cloned.setType( this.getType() );
+
+        for ( final Iterator it = this.children.iterator(); it.hasNext(); ) {
+            RuleConditionElement re = (RuleConditionElement) it.next();
+            if ( re instanceof GroupElement ) {
+                re = (RuleConditionElement) ((GroupElement) re).clone();
+            }
+            cloned.addChild( re );
+        }
+
+        return cloned;
+    }
+
+    public Type getType() {
+        return this.type;
+    }
+
+    public void setType(final Type type) {
+        this.type = type;
+    }
+
+    public boolean isAnd() {
+        return this.type.isAnd();
+    }
+
+    public boolean isOr() {
+        return this.type.isOr();
+    }
+
+    public boolean isNot() {
+        return this.type.isNot();
+    }
+
+    public boolean isExists() {
+        return this.type.isExists();
+    }
+
+    public String toString() {
+        return this.type.toString() + this.children.toString();
+    }
+    
+    public List getNestedElements() {
+        return this.children;
+    }
+
+    /**
+     * A public interface for CE types
+     */
+    public static interface Type
+        extends
+        Serializable {
+
+        /**
+         * Returns true if this CE type is an AND
+         */
+        public boolean isAnd();
+
+        /**
+         * Returns true if this CE type is an OR
+         */
+        public boolean isOr();
+
+        /**
+         * Returns true if this CE type is an NOT
+         */
+        public boolean isNot();
+
+        /**
+         * Returns true if this CE type is an EXISTS
+         */
+        public boolean isExists();
+
+        /**
+         * Returns a map of declarations that are
+         * visible inside of an element of this type
+         */
+        public Map getInnerDeclarations(List children);
+
+        /**
+         * Returns a map of declarations that are
+         * visible outside of an element of this type
+         */
+        public Map getOuterDeclarations(List children);
+    }
+
+    private static abstract class AbstractType
+        implements
+        Type {
+
+        private static final long serialVersionUID = 400L;
+
+        /**
+         * @inheritDoc
+         */
+        public Map getInnerDeclarations(final List children) {
+            Map declarations = null;
+
+            if ( children.isEmpty() ) {
+                declarations = Collections.EMPTY_MAP;
+            } else if ( children.size() == 1 ) {
+                final RuleConditionElement re = (RuleConditionElement) children.get( 0 );
+                declarations = re.getOuterDeclarations();
+            } else {
+                declarations = new HashMap();
+                for ( final Iterator it = children.iterator(); it.hasNext(); ) {
+                    declarations.putAll( ((RuleConditionElement) it.next()).getOuterDeclarations() );
+                }
+            }
+            return declarations;
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public Map getOuterDeclarations(final List children) {
+            Map declarations = null;
+
+            if ( children.isEmpty() ) {
+                declarations = Collections.EMPTY_MAP;
+            } else if ( children.size() == 1 ) {
+                final RuleConditionElement re = (RuleConditionElement) children.get( 0 );
+                declarations = re.getOuterDeclarations();
+            } else {
+                declarations = new HashMap();
+                for ( final Iterator it = children.iterator(); it.hasNext(); ) {
+                    declarations.putAll( ((RuleConditionElement) it.next()).getOuterDeclarations() );
+                }
+            }
+            return declarations;
+        }
+    }
+
+    /**
+     * An AND CE type
+     */
+    private static class AndType extends AbstractType {
+
+        private static final long serialVersionUID = 400L;
+
+        AndType() {
+        }
+
+        public boolean isAnd() {
+            return true;
+        }
+
+        public boolean isExists() {
+            return false;
+        }
+
+        public boolean isNot() {
+            return false;
+        }
+
+        public boolean isOr() {
+            return false;
+        }
+
+        public boolean equals(final Object obj) {
+            if ( !(obj instanceof AndType) ) {
+                return false;
+            }
+            return true;
+        }
+
+        public int hashCode() {
+            return 11;
+        }
+
+        public String toString() {
+            return "AND";
+        }
+
+    }
+
+    /**
+     * An OR CE type
+     */
+    private static class OrType extends AbstractType {
+
+        private static final long serialVersionUID = 400L;
+
+        OrType() {
+        }
+
+        public boolean isAnd() {
+            return false;
+        }
+
+        public boolean isExists() {
+            return false;
+        }
+
+        public boolean isNot() {
+            return false;
+        }
+
+        public boolean isOr() {
+            return true;
+        }
+
+        public boolean equals(final Object obj) {
+            if ( !(obj instanceof OrType) ) {
+                return false;
+            }
+            return true;
+        }
+
+        public int hashCode() {
+            return 17;
+        }
+
+        public String toString() {
+            return "OR";
+        }
+    }
+
+    /**
+     * A NOT CE type
+     */
+    private static class NotType extends AbstractType {
+
+        private static final long serialVersionUID = 400L;
+
+        NotType() {
+        }
+
+        public boolean isAnd() {
+            return false;
+        }
+
+        public boolean isExists() {
+            return false;
+        }
+
+        public boolean isNot() {
+            return true;
+        }
+
+        public boolean isOr() {
+            return false;
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public Map getOuterDeclarations(final List children) {
+            return Collections.EMPTY_MAP;
+        }
+
+        public boolean equals(final Object obj) {
+            if ( !(obj instanceof NotType) ) {
+                return false;
+            }
+            return true;
+        }
+
+        public int hashCode() {
+            return 23;
+        }
+
+        public String toString() {
+            return "NOT";
+        }
+    }
+
+    /**
+     * An EXISTS CE type
+     */
+    private static class ExistsType extends AbstractType {
+
+        private static final long serialVersionUID = 400L;
+
+        ExistsType() {
+        }
+
+        public boolean isAnd() {
+            return false;
+        }
+
+        public boolean isExists() {
+            return true;
+        }
+
+        public boolean isNot() {
+            return false;
+        }
+
+        public boolean isOr() {
+            return false;
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public Map getOuterDeclarations(final List children) {
+            return Collections.EMPTY_MAP;
+        }
+
+        public boolean equals(final Object obj) {
+            if ( !(obj instanceof ExistsType) ) {
+                return false;
+            }
+            return true;
+        }
+
+        public int hashCode() {
+            return 31;
+        }
+
+        public String toString() {
+            return "EXISTS";
+        }
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/GroupElementFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/GroupElementFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/GroupElementFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2006 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.rule;
+
+/**
+ * A simple factory for GroupElements
+ * 
+ * @author etirelli
+ */
+public class GroupElementFactory {
+
+    private GroupElementFactory() {
+    }
+
+    public static GroupElement newAndInstance() {
+        return new GroupElement( GroupElement.AND );
+    }
+
+    public static GroupElement newOrInstance() {
+        return new GroupElement( GroupElement.OR );
+    }
+
+    public static GroupElement newNotInstance() {
+        return new GroupElement( GroupElement.NOT );
+    }
+
+    public static GroupElement newExistsInstance() {
+        return new GroupElement( GroupElement.EXISTS );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/ImportDeclaration.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/ImportDeclaration.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/ImportDeclaration.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Nov 7, 2007
+ */
+package org.drools.rule;
+
+import java.io.Serializable;
+
+/**
+ * A class to represent an import declaration. 
+ * 
+ * @author etirelli
+ */
+public class ImportDeclaration implements Serializable {
+
+    private static final long serialVersionUID = 6410032114027977766L;
+
+    private String target;
+
+    /**
+     * Creates an empty import declaration 
+     */
+    public ImportDeclaration() {
+        this( null );
+    }
+
+    /**
+     * Creates an import declaration for the given target.
+     * 
+     * @param target
+     */
+    public ImportDeclaration( String target ) {
+        super();
+        this.target = target;
+    }
+    
+    public String getTarget() {
+        return target;
+    }
+
+    public void setTarget(String target) {
+        this.target = target;
+    }
+
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + ((target == null) ? 0 : target.hashCode());
+        return result;
+    }
+
+    public boolean equals(Object obj) {
+        if ( this == obj ) return true;
+        if ( obj == null ) return false;
+        if ( getClass() != obj.getClass() ) return false;
+        final ImportDeclaration other = (ImportDeclaration) obj;
+        if ( target == null ) {
+            if ( other.target != null ) return false;
+        } else if ( !target.equals( other.target ) ) return false;
+        return true;
+    }
+
+    /**
+     * Returns true if this ImportDeclaration correctly matches to
+     * the given clazz
+     * 
+     * @param name
+     * @return
+     */
+    public boolean matches( Class<?> clazz ) {
+        // fully qualified import?
+        if( this.target.equals( clazz.getName() ) ) {
+            return true;
+        }
+        
+        // wild card imports
+        if( this.target.endsWith( ".*" ) ) {
+            String prefix = this.target.substring( 0, this.target.indexOf( ".*" ) );
+            
+            // package import: import my.package.*
+            if( prefix.equals( clazz.getPackage().getName() ) ) {
+                return true;
+            }
+            
+            // inner class imports with wild card?
+            // by looking at the ClassTypeResolver class, it seems we do not support
+            // the usage of wild cards when importing static inner classes like the
+            // java static imports allow
+        }
+        return false;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/InvalidPatternException.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/InvalidPatternException.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/InvalidPatternException.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,54 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class InvalidPatternException extends RuleConstructionException {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    /**
+     * @see java.lang.Exception#Exception()
+     */
+    public InvalidPatternException() {
+        super();
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(String message)
+     */
+    public InvalidPatternException(final String message) {
+        super( message );
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(String message, Throwable cause)
+     */
+    public InvalidPatternException(final String message,
+                                   final Throwable cause) {
+        super( message,
+               cause );
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(Throwable cause)
+     */
+    public InvalidPatternException(final Throwable cause) {
+        super( cause );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/InvalidRuleException.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/InvalidRuleException.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/InvalidRuleException.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,77 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Indicates an error regarding the semantic validity of a rule.
+ * 
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter </a>
+ */
+public class InvalidRuleException extends RuleConstructionException {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+    /** The invalid rule. */
+    private Rule              rule;
+
+    /**
+     * @see java.lang.Exception#Exception()
+     * 
+     * @param rule
+     *            The invalid <code>Rule</code>.
+     */
+    public InvalidRuleException(final Rule rule) {
+        super();
+        this.rule = rule;
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(String message)
+     * 
+     * @param message
+     * @param rule
+     */
+    public InvalidRuleException(final String message,
+                                final Rule rule) {
+        super( message );
+        this.rule = rule;
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(String message, Throwable cause)
+     * 
+     * @param message
+     * @param rule
+     */
+    public InvalidRuleException(final String message,
+                                final Rule rule,
+                                final Throwable cause) {
+        super( message,
+               cause );
+        this.rule = rule;
+    }
+
+    /**
+     * Retrieve the invalid <code>Rule</code>.
+     * 
+     * @return The invalid <code>Rule</code>.
+     */
+    public Rule getRule() {
+        return this.rule;
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/InvalidRulePackage.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/InvalidRulePackage.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/InvalidRulePackage.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,34 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * This exception is thrown when an invalid package (ie one that has errors)
+ * it attempted to be added to a RuleBase.
+ * The package and builder should be interrogated to show the specific errors.
+ * 
+ * @author Michael Neale
+ */
+public class InvalidRulePackage extends RuntimeException {
+
+    private static final long serialVersionUID = 400L;
+
+    public InvalidRulePackage(final String summary) {
+        super( summary );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/LineMappings.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/LineMappings.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/LineMappings.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,32 @@
+package org.drools.rule;
+
+public class LineMappings {
+    private String className;
+    private int    startLine;
+    private int    offset;
+
+    public LineMappings(final String className) {
+        this.className = className;
+    }
+
+    public String getClassName() {
+        return this.className;
+    }
+
+    public void setStartLine(final int startLine) {
+        this.startLine = startLine;
+    }
+
+    public int getStartLine() {
+        return this.startLine;
+    }
+
+    public void setOffset(final int offset) {
+        this.offset = offset;
+    }
+
+    public int getOffset() {
+        return this.offset;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/LiteralConstraint.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/LiteralConstraint.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/LiteralConstraint.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,117 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.FieldValue;
+
+public class LiteralConstraint
+    implements
+    AlphaNodeFieldConstraint {
+
+    /**
+     * 
+     */
+    private static final long        serialVersionUID = 400L;
+
+    private final FieldExtractor     extractor;
+
+    private final LiteralRestriction restriction;
+
+    public LiteralConstraint(final FieldExtractor extractor,
+                             final Evaluator evaluator,
+                             final FieldValue field) {
+        this.extractor = extractor;
+        this.restriction = new LiteralRestriction( field,
+                                                   evaluator,
+                                                   extractor );
+    }
+
+    public LiteralConstraint(final FieldExtractor extractor,
+                             final LiteralRestriction restriction) {
+        this.extractor = extractor;
+        this.restriction = restriction;
+    }
+
+    public Evaluator getEvaluator() {
+        return this.restriction.getEvaluator();
+    }
+
+    public FieldValue getField() {
+        return this.restriction.getField();
+    }
+
+    public FieldExtractor getFieldExtractor() {
+        return this.extractor;
+    }
+
+    /**
+     * Literal constraints cannot have required declarations, so always return an empty array.
+     * @return
+     *      Return an empty <code>Declaration[]</code>
+     */
+    public Declaration[] getRequiredDeclarations() {
+        return this.restriction.getRequiredDeclarations();
+    }
+
+    public void replaceDeclaration(Declaration oldDecl,
+                                   Declaration newDecl) {
+        this.restriction.replaceDeclaration( oldDecl,
+                                             newDecl );
+    }
+
+    public boolean isAllowed(final InternalFactHandle handle,
+                             final InternalWorkingMemory workingMemory) {
+        return this.restriction.isAllowed( this.extractor,
+                                           handle,
+                                           workingMemory );
+    }
+
+    public String toString() {
+        return "[LiteralConstraint fieldExtractor=" + this.extractor + " evaluator=" + getEvaluator() + " value=" + getField() + "]";
+    }
+
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + this.extractor.hashCode();
+        result = PRIME * result + this.restriction.hashCode();
+        return result;
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+        if ( object == null || object.getClass() != LiteralConstraint.class ) {
+            return false;
+        }
+        final LiteralConstraint other = (LiteralConstraint) object;
+
+        return this.extractor.equals( other.extractor ) && this.restriction.equals( other.restriction );
+    }
+
+    public Object clone() {
+        return new LiteralConstraint( this.extractor,
+                                      this.getEvaluator(),
+                                      this.getField() );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/LiteralRestriction.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/LiteralRestriction.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/LiteralRestriction.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,178 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.FieldValue;
+import org.drools.spi.Restriction;
+
+public class LiteralRestriction
+    implements
+    Restriction {
+
+    private static final long          serialVersionUID     = 400L;
+
+    private final FieldValue           field;
+
+    private final Evaluator            evaluator;
+
+    private static final Declaration[] requiredDeclarations = new Declaration[0];
+
+    private final LiteralContextEntry  contextEntry;
+
+    public LiteralRestriction(final FieldValue field,
+                              final Evaluator evaluator,
+                              final FieldExtractor fieldExtractor) {
+        this.field = field;
+        this.evaluator = evaluator;
+        this.contextEntry = new LiteralContextEntry( fieldExtractor );
+    }
+
+    public Evaluator getEvaluator() {
+        return this.evaluator;
+    }
+
+    public FieldValue getField() {
+        return this.field;
+    }
+
+    public boolean isAllowed(final Extractor extractor,
+                             final InternalFactHandle handle,
+                             final InternalWorkingMemory workingMemoiry) {
+        return this.evaluator.evaluate( null,
+                                        extractor,
+                                        handle.getObject(),
+                                        this.field );
+    }
+
+    public boolean isAllowedCachedLeft(final ContextEntry context,
+                                       final InternalFactHandle handle) {
+        return this.evaluator.evaluate( null,
+                                        ((LiteralContextEntry) context).getFieldExtractor(),
+                                        handle.getObject(),
+                                        this.field );
+    }
+
+    public boolean isAllowedCachedRight(final ReteTuple tuple,
+                                        final ContextEntry context) {
+        return this.evaluator.evaluate( null,
+                                        ((LiteralContextEntry) context).getFieldExtractor(),
+                                        ((LiteralContextEntry) context).getObject(),
+                                        this.field );
+    }
+
+    /**
+     * Literal constraints cannot have required declarations, so always return an empty array.
+     * @return
+     *      Return an empty <code>Declaration[]</code>
+     */
+    public Declaration[] getRequiredDeclarations() {
+        return LiteralRestriction.requiredDeclarations;
+    }
+
+    public void replaceDeclaration(Declaration oldDecl,
+                                   Declaration newDecl) {
+    }
+
+    public String toString() {
+        return "[LiteralRestriction evaluator=" + this.evaluator + " value=" + this.field + "]";
+    }
+
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + this.evaluator.hashCode();
+        result = PRIME * result + ((this.field.getValue() != null) ? this.field.getValue().hashCode() : 0);
+        return result;
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+        if ( object == null || object.getClass() != LiteralRestriction.class ) {
+            return false;
+        }
+        final LiteralRestriction other = (LiteralRestriction) object;
+
+        return this.field.equals( other.field ) && this.evaluator.equals( other.evaluator );
+    }
+
+    public ContextEntry getContextEntry() {
+        return this.contextEntry;
+    }
+
+    public Object clone() {
+        return new LiteralRestriction( this.field,
+                                       this.evaluator,
+                                       this.contextEntry.extractor );
+    }
+
+    private static class LiteralContextEntry
+        implements
+        ContextEntry {
+
+        private static final long serialVersionUID = 2621864784428098347L;
+        public FieldExtractor     extractor;
+        public Object             object;
+        public ContextEntry       next;
+
+        public LiteralContextEntry(final FieldExtractor extractor) {
+            this.extractor = extractor;
+        }
+
+        public FieldExtractor getFieldExtractor() {
+            return this.extractor;
+        }
+
+        public Object getObject() {
+            return this.object;
+        }
+
+        public ContextEntry getNext() {
+            return this.next;
+        }
+
+        public void setNext(final ContextEntry entry) {
+            this.next = entry;
+        }
+
+        public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
+                                         final InternalFactHandle handle) {
+            this.object = handle.getObject();
+        }
+
+        public void updateFromTuple(final InternalWorkingMemory workingMemory,
+                                    final ReteTuple tuple) {
+            // nothing to do
+        }
+        
+        public void resetTuple() {            
+        }
+        
+        public void resetFactHandle() {
+            this.object = null;
+        }        
+
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/LogicTransformer.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/LogicTransformer.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/LogicTransformer.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,448 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Stack;
+
+import org.drools.spi.Constraint;
+import org.drools.spi.DeclarationScopeResolver;
+
+/**
+ * LogicTransformation is reponsible for removing redundant nodes and move Or
+ * nodes upwards.
+ * 
+ * This class does not turn Exists into two Nots at this stage, that role is
+ * delegated to the Builder.
+ * 
+ * @author mproctor
+ * 
+ */
+class LogicTransformer {
+    private final Map               orTransformations = new HashMap();
+
+    private static LogicTransformer INSTANCE          = null;
+
+    static LogicTransformer getInstance() {
+        if ( LogicTransformer.INSTANCE == null ) {
+            LogicTransformer.INSTANCE = new LogicTransformer();
+        }
+
+        return LogicTransformer.INSTANCE;
+    }
+
+    LogicTransformer() {
+        initialize();
+    }
+
+    /**
+     * sets up the parent->child transformations map
+     * 
+     */
+    private void initialize() {
+        // these pairs will be transformed
+        addTransformationPair( GroupElement.NOT,
+                               new NotOrTransformation() );
+        addTransformationPair( GroupElement.EXISTS,
+                               new ExistOrTransformation() );
+        addTransformationPair( GroupElement.AND,
+                               new AndOrTransformation() );
+    }
+
+    private void addTransformationPair(final GroupElement.Type parent,
+                                       final Transformation method) {
+        this.orTransformations.put( parent,
+                                    method );
+    }
+
+    public GroupElement[] transform(final GroupElement and) throws InvalidPatternException {
+        final GroupElement cloned = (GroupElement) and.clone();
+
+        processTree( cloned );
+        cloned.pack();
+
+        GroupElement[] ands = null;
+        // is top element an AND?
+        if ( cloned.isAnd() ) {
+            // Yes, so just return it
+            ands = new GroupElement[]{cloned};
+        } else if ( cloned.isOr() ) {
+            // it is an OR, so each child is an AND branch
+            ands = new GroupElement[cloned.getChildren().size()];
+            int i = 0;
+            for ( final Iterator it = cloned.getChildren().iterator(); it.hasNext(); ) {
+                final RuleConditionElement branch = (RuleConditionElement) it.next();
+                if ( (branch instanceof GroupElement) && (((GroupElement) branch).isAnd()) ) {
+                    ands[i++] = (GroupElement) branch;
+                } else {
+                    ands[i] = GroupElementFactory.newAndInstance();
+                    ands[i].addChild( branch );
+                    i++;
+                }
+            }
+        } else {
+            // no, so just wrap into an AND
+            final GroupElement wrapper = GroupElementFactory.newAndInstance();
+            wrapper.addChild( cloned );
+            ands = new GroupElement[]{wrapper};
+        }
+
+        for ( int i = 0; i < ands.length; i++ ) {
+            // fix the cloned declarations
+            this.fixClonedDeclarations( ands[i] );
+        }
+
+        return ands;
+    }
+
+    /**
+     * During the logic transformation, we eventually clone CEs, 
+     * specially patterns and corresponding declarations. So now
+     * we need to fix any references to cloned declarations.
+     * @param ands
+     */
+    private void fixClonedDeclarations(GroupElement and) {
+        Stack contextStack = new Stack();
+        DeclarationScopeResolver resolver = new DeclarationScopeResolver( new Map[0],
+                                                                          contextStack );
+
+        contextStack.push( and );
+        processElement( resolver,
+                        contextStack,
+                        and );
+        contextStack.pop();
+    }
+
+    /**
+     * recurse through the rule condition elements updating the declaration objecs
+     * @param resolver
+     * @param contextStack
+     * @param element
+     */
+    private void processElement(final DeclarationScopeResolver resolver,
+                                final Stack contextStack,
+                                final RuleConditionElement element) {
+        if ( element instanceof Pattern ) {
+            Pattern pattern = (Pattern) element;
+            for ( Iterator it = pattern.getNestedElements().iterator(); it.hasNext(); ) {
+                processElement( resolver,
+                                contextStack,
+                                (RuleConditionElement) it.next() );
+            }
+            for ( Iterator it = pattern.getConstraints().iterator(); it.hasNext(); ) {
+                Object next = it.next();
+                if ( next instanceof Declaration ) {
+                    continue;
+                }
+                Constraint constraint = (Constraint) next;
+                Declaration[] decl = constraint.getRequiredDeclarations();
+                for ( int i = 0; i < decl.length; i++ ) {
+                    Declaration resolved = resolver.getDeclaration( decl[i].getIdentifier() );
+                    if ( resolved != null && resolved != decl[i] ) {
+                        constraint.replaceDeclaration( decl[i],
+                                                       resolved );
+                    }
+                }
+            }
+        } else {
+            contextStack.push( element );
+            for ( Iterator it = element.getNestedElements().iterator(); it.hasNext(); ) {
+                processElement( resolver,
+                                contextStack,
+                                (RuleConditionElement) it.next() );
+            }
+            contextStack.pop();
+        }
+    }
+
+    /**
+     * Traverses a Tree, during the process it transforms Or nodes moving the
+     * upwards and it removes duplicate logic statement, this does not include
+     * Not nodes.
+     * 
+     * Traversal involves three levels the graph for each iteration. The first
+     * level is the current node, this node will not be transformed, instead
+     * what we are interested in are the children of the current node (called
+     * the parent nodes) and the children of those parents (call the child
+     * nodes).
+     * 
+     * @param ce
+     */
+    void processTree(final GroupElement ce) throws InvalidPatternException {
+
+        boolean hasChildOr = false;
+
+        // first we elimininate any redundancy
+        ce.pack();
+
+        Object[] children = (Object[]) ce.getChildren().toArray(); 
+        for ( int i = 0; i < children.length; i++ ) {
+            if ( children[i] instanceof GroupElement ) {
+                final GroupElement child = (GroupElement) children[i];
+
+                processTree( child );
+                if( ( child.isOr() || child.isAnd() ) && child.getType() == ce.getType() ) {
+                    child.pack( ce );
+                } else if ( child.isOr() ) {
+                    hasChildOr = true;
+                }
+            }
+        }
+        
+        if ( hasChildOr ) {
+            applyOrTransformation( ce );
+        }
+    }
+
+    void applyOrTransformation(final GroupElement parent) throws InvalidPatternException {
+        final Transformation transformation = (Transformation) this.orTransformations.get( parent.getType() );
+
+        if ( transformation == null ) {
+            throw new RuntimeException( "applyOrTransformation could not find transformation for parent '" + parent.getType() + "' and child 'OR'" );
+        }
+        transformation.transform( parent );
+    }
+
+    interface Transformation {
+        void transform(GroupElement element) throws InvalidPatternException;
+    }
+
+    /**
+     * Takes any And that has an Or as a child and rewrites it to move the Or
+     * upwards
+     * 
+     * (a||b)&&c
+     * 
+     * <pre>
+     *             and
+     *             / \
+     *            or  c 
+     *           /  \
+     *          a    b
+     * </pre>
+     * 
+     * Should become (a&&c)||(b&&c)
+     * 
+     * <pre>
+     *               
+     *             or
+     *            /  \  
+     *           /    \ 
+     *          /      \ 
+     *        and      and     
+     *        / \      / \
+     *       a   c    b   c
+     * </pre>
+     */
+    class AndOrTransformation
+        implements
+        Transformation {
+
+        public void transform(final GroupElement parent) throws InvalidPatternException {
+            final List orsList = new ArrayList();
+            // must keep order, so, using array
+            final Object[] others = new Object[parent.getChildren().size()];
+
+            // first we split children as OR or not OR
+            int permutations = 1;
+            int index = 0;
+            for ( final Iterator it = parent.getChildren().iterator(); it.hasNext(); ) {
+                final Object child = it.next();
+                if ( (child instanceof GroupElement) && ((GroupElement) child).isOr() ) {
+                    permutations *= ((GroupElement) child).getChildren().size();
+                    orsList.add( child );
+                } else {
+                    others[index] = child;
+                }
+                index++;
+            }
+
+            // transform parent into an OR
+            parent.setType( GroupElement.OR );
+            parent.getChildren().clear();
+
+            // prepare arrays and indexes to calculate permutation
+            final GroupElement[] ors = (GroupElement[]) orsList.toArray( new GroupElement[orsList.size()] );
+            final int[] indexes = new int[ors.length];
+
+            // now we know how many permutations we will have, so create it
+            for ( int i = 1; i <= permutations; i++ ) {
+                final GroupElement and = GroupElementFactory.newAndInstance();
+
+                // create the actual permutations
+                int mod = 1;
+                for ( int j = ors.length - 1; j >= 0; j-- ) {
+                    // we must insert at the beggining to keep the order
+                    and.getChildren().add( 0,
+                                           ors[j].getChildren().get( indexes[j] ) );
+                    if ( (i % mod) == 0 ) {
+                        indexes[j] = (indexes[j] + 1) % ors[j].getChildren().size();
+                    }
+                    mod *= ors[j].getChildren().size();
+                }
+
+                // elements originally outside OR will be in every permutation, so add them
+                // in their original position
+                for ( int j = 0; j < others.length; j++ ) {
+                    if ( others[j] != null ) {
+                        // always add clone of them to avoid offset conflicts in declarations
+
+                        // HERE IS THE MESSY PROBLEM: need to change further references to the appropriate cloned ref
+                        and.getChildren().add( j,
+                                               ((RuleConditionElement) others[j]).clone() );
+                    }
+                }
+                parent.addChild( and );
+            }
+
+            // remove duplications
+            parent.pack();
+        }
+    }
+
+    /**
+     * (Exist (OR (A B)
+     * 
+     * <pre>
+     *         Exist
+     *          | 
+     *         or   
+     *        /  \
+     *       a    b
+     * </pre>
+     * 
+     * (Exist ( Not (a) Not (b)) )
+     * 
+     * <pre>
+     *          Or   
+     *        /   \
+     *    Exists  Exists
+     *      |       |
+     *      a       b
+     * </pre>
+     */
+    class ExistOrTransformation
+        implements
+        Transformation {
+
+        public void transform(final GroupElement parent) throws InvalidPatternException {
+            if ( (!(parent.getChildren().get( 0 ) instanceof GroupElement)) && (((GroupElement) parent.getChildren().get( 0 )).isExists()) ) {
+                throw new RuntimeException( "ExistOrTransformation expected 'OR' but instead found '" + parent.getChildren().get( 0 ).getClass().getName() + "'" );
+            }
+
+            /*
+             * we know an Exists only ever has one child, and the previous algorithm
+             * has confirmed the child is an OR
+             */
+            final GroupElement or = (GroupElement) parent.getChildren().get( 0 );
+            parent.setType( GroupElement.OR );
+            parent.getChildren().clear();
+            for ( final Iterator it = or.getChildren().iterator(); it.hasNext(); ) {
+                final GroupElement newExists = GroupElementFactory.newExistsInstance();
+                newExists.addChild( (RuleConditionElement) it.next() );
+                parent.addChild( newExists );
+            }
+            parent.pack();
+        }
+    }
+
+    /**
+     * (Not (OR (A B)
+     * 
+     * <pre>
+     *         Not
+     *          | 
+     *         or   
+     *        /  \
+     *       a    b
+     * </pre>
+     * 
+     * (And ( Not (a) Exist (b)) )
+     * 
+     * <pre>
+     *         And   
+     *        /   \
+     *       Not  Not
+     *       |     |
+     *       a     b
+     * </pre>
+     */
+    public class NotOrTransformation
+        implements
+        Transformation {
+
+        public void transform(final GroupElement parent) throws InvalidPatternException {
+
+            if ( (!(parent.getChildren().get( 0 ) instanceof GroupElement)) && (((GroupElement) parent.getChildren().get( 0 )).isOr()) ) {
+                throw new RuntimeException( "NotOrTransformation expected 'OR' but instead found '" + parent.getChildren().get( 0 ).getClass().getName() + "'" );
+            }
+
+            /*
+             * we know a Not only ever has one child, and the previous algorithm
+             * has confirmed the child is an OR
+             */
+            final GroupElement or = (GroupElement) parent.getChildren().get( 0 );
+            parent.setType( GroupElement.AND );
+            parent.getChildren().clear();
+            for ( final Iterator it = or.getChildren().iterator(); it.hasNext(); ) {
+                final GroupElement newNot = GroupElementFactory.newNotInstance();
+                newNot.addChild( (RuleConditionElement) it.next() );
+                parent.addChild( newNot );
+            }
+            parent.pack();
+        }
+    }
+
+    //@todo for 3.1
+    //    public class NotAndTransformation
+    //        implements
+    //        Transformation {
+    //
+    //        public GroupElement transform(GroupElement not) throws InvalidPatternException {
+    //            if ( !(not.getChildren().get( 0 ) instanceof And) ) {
+    //                throw new RuntimeException( "NotAndTransformation expected '" + And.class.getName() + "' but instead found '" + not.getChildren().get( 0 ).getClass().getName() + "'" );
+    //            }
+    //
+    //            /*
+    //             * we know a Not only ever has one child, and the previous algorithm
+    //             * has confirmed the child is an And
+    //             */
+    //            And and = (And) not.getChildren().get( 0 );
+    //            for ( Iterator it = and.getChildren().iterator(); it.hasNext(); ) {
+    //                Object object1 = it.next();
+    //
+    //                for ( Iterator it2 = and.getChildren().iterator(); it.hasNext(); ) {
+    //                    Object object2 = it.next();
+    //                    if ( object2 != object1 ) {
+    //
+    //                    }
+    //                }
+    //
+    //                Not newNot = new Not();
+    //                newNot.addChild( it.next() );
+    //                and.addChild( newNot );
+    //            }
+    //
+    //            return and;
+    //        }
+    //    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/MapBackedClassLoader.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/MapBackedClassLoader.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/MapBackedClassLoader.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,118 @@
+package org.drools.rule;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.util.HashMap;
+import java.util.Map;
+
+public class MapBackedClassLoader extends ClassLoader
+    implements
+    DroolsClassLoader,
+    Serializable {
+	
+	private static final long serialVersionUID = 400L;
+
+	private static final ProtectionDomain PROTECTION_DOMAIN;
+    
+    private Map store;
+
+    static {
+        PROTECTION_DOMAIN = (ProtectionDomain) AccessController.doPrivileged( new PrivilegedAction() {
+            public Object run() {
+                return MapBackedClassLoader.class.getProtectionDomain();
+            }
+        } );
+    }    
+
+    public MapBackedClassLoader(final ClassLoader parentClassLoader) {
+        super( parentClassLoader );
+        this.store = new HashMap();
+    }
+    
+    public void addResource(String className,
+                            byte[] bytes) {
+        addClass(className, 
+                 bytes);
+    }
+    
+    private String convertResourcePathToClassName(final String pName) {
+    	return pName.replaceAll(".java$|.class$", "").replace('/', '.');
+    }
+    
+
+    public void addClass(final String className,
+                         byte[] bytes) {
+    	
+        this.store.put( convertResourcePathToClassName(className),
+                        bytes );
+    }
+
+    public Class fastFindClass(final String name) {
+        final Class clazz = findLoadedClass( name );
+
+        if ( clazz == null ) {
+            final byte[] clazzBytes = (byte[]) this.store.get( name );
+            if ( clazzBytes != null ) {
+                return defineClass( name,
+                                    clazzBytes,
+                                    0,
+                                    clazzBytes.length,
+                                    PROTECTION_DOMAIN );
+            }
+        }
+        return clazz;
+    }
+
+    /**
+     * Javadocs recommend that this method not be overloaded. We overload this so that we can prioritise the fastFindClass 
+     * over method calls to parent.loadClass(name, false); and c = findBootstrapClass0(name); which the default implementation
+     * would first - hence why we call it "fastFindClass" instead of standard findClass, this indicates that we give it a 
+     * higher priority than normal.
+     * 
+     */
+    protected synchronized Class loadClass(final String name,
+                                           final boolean resolve) throws ClassNotFoundException {
+        Class clazz = fastFindClass( name );
+
+        if ( clazz == null ) {
+            final ClassLoader parent = getParent();
+            if ( parent != null ) {
+                clazz = parent.loadClass( name );
+            } else {
+                throw new ClassNotFoundException( name );
+            }
+        }
+
+        if ( resolve ) {
+            resolveClass( clazz );
+        }
+
+        return clazz;
+    }
+
+    protected Class findClass(final String name) throws ClassNotFoundException {
+        final Class clazz = fastFindClass( name );
+        if ( clazz == null ) {
+            throw new ClassNotFoundException( name );
+        }
+        return clazz;
+    }
+
+    public InputStream getResourceAsStream(final String name) {
+        final byte[] bytes = (byte[]) this.store.get( name );
+        if ( bytes != null ) {
+            return new ByteArrayInputStream( bytes );
+        } else {
+            InputStream input = this.getParent().getResourceAsStream( name );
+            if ( input == null ) {
+                input = super.getResourceAsStream( name );
+            }
+            return input;
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/MultiRestrictionFieldConstraint.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/MultiRestrictionFieldConstraint.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/MultiRestrictionFieldConstraint.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,97 @@
+package org.drools.rule;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.Restriction;
+
+public class MultiRestrictionFieldConstraint
+    implements
+    AlphaNodeFieldConstraint,
+    BetaNodeFieldConstraint {
+
+    /**
+     * 
+     */
+    private static final long    serialVersionUID = 400L;
+
+    private final FieldExtractor extractor;
+
+    private final Restriction    restrictions;
+
+    public MultiRestrictionFieldConstraint(final FieldExtractor extractor,
+                                           final Restriction restrictions) {
+        this.extractor = extractor;
+        this.restrictions = restrictions;
+    }
+
+    public FieldExtractor getFieldExtractor() {
+        return this.extractor;
+    }
+
+    public Declaration[] getRequiredDeclarations() {
+        return this.restrictions.getRequiredDeclarations();
+    }
+
+    public void replaceDeclaration(Declaration oldDecl,
+                                   Declaration newDecl) {
+        this.restrictions.replaceDeclaration( oldDecl,
+                                              newDecl );
+    }
+
+    public String toString() {
+        return "[MultiRestrictionConstraint fieldExtractor=" + this.extractor + " restrictions =" + this.restrictions + "]";
+    }
+
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * this.extractor.hashCode();
+        result = PRIME * this.restrictions.hashCode();
+        return result;
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+        if ( object == null || object.getClass() != MultiRestrictionFieldConstraint.class ) {
+            return false;
+        }
+        final MultiRestrictionFieldConstraint other = (MultiRestrictionFieldConstraint) object;
+
+        return this.extractor.equals( other.extractor ) && this.restrictions.equals( other.restrictions );
+    }
+
+    public boolean isAllowed(final InternalFactHandle handle,
+                             final InternalWorkingMemory workingMemory) {
+        return this.restrictions.isAllowed( this.extractor,
+                                            handle,
+                                            workingMemory );
+    }
+
+    public ContextEntry getContextEntry() {
+        return this.restrictions.getContextEntry();
+    }
+
+    public boolean isAllowedCachedLeft(final ContextEntry context,
+                                       final InternalFactHandle handle) {
+        return this.restrictions.isAllowedCachedLeft( context,
+                                                      handle );
+    }
+
+    public boolean isAllowedCachedRight(final ReteTuple tuple,
+                                        final ContextEntry context) {
+        return this.restrictions.isAllowedCachedRight( tuple,
+                                                       context );
+    }
+
+    public Object clone() {
+        return new MultiRestrictionFieldConstraint( this.extractor,
+                                                    (Restriction) this.restrictions.clone() );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/NoConsequenceException.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/NoConsequenceException.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/NoConsequenceException.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,44 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Validity exception indicating that a <code>Rule</code> does not contain a
+ * <code>Consequence</code>s.
+ * 
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter </a>
+ */
+public class NoConsequenceException extends InvalidRuleException {
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    /**
+     * Construct.
+     * 
+     * @param rule
+     *            The invalid <code>Rule</code>.
+     */
+    public NoConsequenceException(final Rule rule) {
+        super( rule );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/OrCompositeRestriction.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/OrCompositeRestriction.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/OrCompositeRestriction.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,59 @@
+package org.drools.rule;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.spi.Extractor;
+import org.drools.spi.Restriction;
+
+public class OrCompositeRestriction extends AbstractCompositeRestriction {
+
+    private static final long serialVersionUID = 400L;
+
+    public OrCompositeRestriction(final Restriction[] restriction) {
+        super( restriction );
+    }
+
+    public boolean isAllowed(final Extractor extractor,
+                             final InternalFactHandle handle,
+                             final InternalWorkingMemory workingMemory) {
+        for ( int i = 0, ilength = this.restrictions.length; i < ilength; i++ ) {
+            if ( this.restrictions[i].isAllowed( extractor,
+                                                 handle,
+                                                 workingMemory ) ) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean isAllowedCachedLeft(final ContextEntry context,
+                                       final InternalFactHandle handle) {
+        for ( int i = 0, ilength = this.restrictions.length; i < ilength; i++ ) {
+            if ( this.restrictions[i].isAllowedCachedLeft( this.contextEntry.contextEntries[i],
+                                                           handle ) ) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean isAllowedCachedRight(final ReteTuple tuple,
+                                        final ContextEntry context) {
+        for ( int i = 0, ilength = this.restrictions.length; i < ilength; i++ ) {
+            if ( this.restrictions[i].isAllowedCachedRight( tuple,
+                                                            this.contextEntry.contextEntries[i] ) ) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public Object clone() {
+        Restriction[] clone = new Restriction[ this.restrictions.length ];
+        for( int i = 0; i < clone.length; i++ ) {
+            clone[i] = (Restriction) this.restrictions[i].clone();
+        }
+        return new OrCompositeRestriction( clone );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/OrConstraint.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/OrConstraint.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/OrConstraint.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.rule;
+
+import java.util.Arrays;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.util.ArrayUtils;
+
+/**
+ * A class to implement Multi-Field OR constraints, so user can do:
+ * 
+ * Person( hair == 'blue' || eyes == 'blue' )
+ * 
+ * @author etirelli
+ *
+ */
+public class OrConstraint extends AbstractCompositeConstraint {
+
+    private static final long serialVersionUID = 400L;
+
+    public OrConstraint() {
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isAllowed(InternalFactHandle handle,
+                             InternalWorkingMemory workingMemory) {
+        if ( this.alphaConstraints.length > 0 ) {
+            for ( int i = 0; i < this.alphaConstraints.length; i++ ) {
+                if ( this.alphaConstraints[i].isAllowed( handle,
+                                                         workingMemory ) ) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isAllowedCachedLeft(ContextEntry context,
+                                       InternalFactHandle handle) {
+        if ( this.betaConstraints.length > 0 ) {
+            for ( int i = 0; i < this.betaConstraints.length; i++ ) {
+                if ( this.betaConstraints[i].isAllowedCachedLeft( ((MultiFieldConstraintContextEntry)context).contexts[i],
+                                                                  handle ) ) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isAllowedCachedRight(ReteTuple tuple,
+                                        ContextEntry context) {
+        if ( this.betaConstraints.length > 0 ) {
+            for ( int i = 0; i < this.betaConstraints.length; i++ ) {
+                if ( this.betaConstraints[i].isAllowedCachedRight( tuple,
+                                                                   ((MultiFieldConstraintContextEntry)context).contexts[i] ) ) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        return true;
+    }
+
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 3; // to differentiate from AND constraint
+        result = PRIME * result + ArrayUtils.hashCode( this.alphaConstraints );
+        result = PRIME * result + ArrayUtils.hashCode( this.betaConstraints );
+        result = PRIME * result + ArrayUtils.hashCode( this.requiredDeclarations );
+        return result;
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+        if ( object == null || object.getClass() != OrConstraint.class ) {
+            return false;
+        }
+        final OrConstraint other = (OrConstraint) object;
+
+        return Arrays.equals( this.alphaConstraints,
+                              other.alphaConstraints ) && Arrays.equals( this.betaConstraints,
+                                                                         other.betaConstraints ) && Arrays.equals( this.requiredDeclarations,
+                                                                                                                   other.requiredDeclarations );
+    }
+
+    public Object clone() {
+        OrConstraint clone = new OrConstraint();
+        
+        // clone alpha constraints
+        clone.alphaConstraints = new AlphaNodeFieldConstraint[ this.alphaConstraints.length ];
+        for( int i = 0; i < this.alphaConstraints.length; i++ ) {
+            clone.alphaConstraints[i] = (AlphaNodeFieldConstraint) this.alphaConstraints[i].clone();
+            clone.updateRequiredDeclarations( clone.alphaConstraints[i] );
+        }
+        
+        // clone beta constraints
+        clone.betaConstraints = new BetaNodeFieldConstraint[ this.betaConstraints.length ];
+        for( int i = 0; i < this.betaConstraints.length; i++ ) {
+            clone.betaConstraints[i] = (BetaNodeFieldConstraint) this.betaConstraints[i].clone();
+            clone.updateRequiredDeclarations( clone.betaConstraints[i] );
+        }
+        
+        return clone;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Package.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Package.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Package.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,502 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.drools.common.DroolsObjectInputStream;
+import org.drools.facttemplates.FactTemplate;
+import org.drools.process.core.Process;
+import org.drools.util.StringUtils;
+
+/**
+ * Collection of related <code>Rule</code>s.
+ *
+ * @see Rule
+ *
+ * @author <a href="mail:bob at werken.com">bob mcwhirter </a>
+ *
+ * @version $Id: Package.java,v 1.1 2005/07/26 01:06:31 mproctor Exp $
+ */
+public class Package
+    implements
+    Externalizable {
+    // ------------------------------------------------------------
+    // Constants`
+    // ------------------------------------------------------------
+
+    /**
+     *
+     */
+    private static final long              serialVersionUID = 400L;
+
+    // ------------------------------------------------------------
+    // Instance members
+    // ------------------------------------------------------------
+
+    /** Name of the pkg. */
+    private String                         name;
+
+    /** Set of all rule-names in this <code>Package</code>. */
+    private Map                            rules;
+
+    private Map<String, ImportDeclaration> imports;
+
+    private List                           functions;
+
+    private Set                            staticImports;
+
+    private Map                            globals;
+
+    private Map                            factTemplates;
+
+    private Map                            ruleFlows;
+
+    private PackageCompilationData         packageCompilationData;
+    
+    private Map<String, TypeDeclaration>   typeDeclarations;
+
+    /** This is to indicate the the package has no errors during the compilation/building phase */
+    private boolean                        valid            = true;
+
+    /** This will keep a summary error message as to why this package is not valid */
+    private String                         errorSummary;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    /**
+     * Default constructor - for Externalizable. This should never be used by a user, as it
+     * will result in an invalid state for the instance.
+     */
+    public Package() {
+
+    }
+
+    /**
+     * Construct.
+     *
+     * @param name
+     *            The name of this <code>Package</code>.
+     */
+    public Package(final String name) {
+        this( name,
+              null );
+    }
+
+    /**
+     * Construct.
+     *
+     * @param name
+     *            The name of this <code>Package</code>.
+     */
+    public Package(final String name,
+                   ClassLoader parentClassLoader) {
+        this.name = name;
+        this.imports = new HashMap<String, ImportDeclaration>();
+        this.typeDeclarations = new HashMap<String, TypeDeclaration>();
+        this.staticImports = Collections.EMPTY_SET;
+        this.rules = new LinkedHashMap();
+        this.ruleFlows = Collections.EMPTY_MAP;
+        this.globals = Collections.EMPTY_MAP;
+        this.factTemplates = Collections.EMPTY_MAP;
+        this.functions = Collections.EMPTY_LIST;
+
+        // This classloader test should only be here for unit testing, too much legacy api to want to change by hand at the moment
+        if ( parentClassLoader == null ) {
+            parentClassLoader = Thread.currentThread().getContextClassLoader();
+            if ( parentClassLoader == null ) {
+                parentClassLoader = getClass().getClassLoader();
+            }
+        }
+        this.packageCompilationData = new PackageCompilationData( parentClassLoader );
+    }
+
+    /**
+     * Handles the write serialization of the Package. Patterns in Rules may reference generated data which cannot be serialized by default methods.
+     * The Package uses PackageCompilationData to hold a reference to the generated bytecode. The generated bytecode must be restored before any Rules.
+     *
+     */
+    public void writeExternal(final ObjectOutput stream) throws IOException {
+        stream.writeObject( this.packageCompilationData );
+        stream.writeObject( this.name );
+        stream.writeObject( this.imports );
+        stream.writeObject( this.staticImports );
+        stream.writeObject( this.typeDeclarations );
+        stream.writeObject( this.functions );
+        stream.writeObject( this.factTemplates );
+        stream.writeObject( this.ruleFlows );
+        stream.writeObject( this.globals );
+        stream.writeBoolean( this.valid );
+
+        // Rules must be restored by an ObjectInputStream that can resolve using a given ClassLoader to handle seaprately by storing as
+        // a byte[]
+        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        final ObjectOutput out = new ObjectOutputStream( bos );
+        out.writeObject( this.rules );
+        stream.writeObject( bos.toByteArray() );
+    }
+
+    /**
+     * Handles the read serialization of the Package. Patterns in Rules may reference generated data which cannot be serialized by default methods.
+     * The Package uses PackageCompilationData to hold a reference to the generated bytecode; which must be restored before any Rules.
+     * A custom ObjectInputStream, able to resolve classes against the bytecode in the PackageCompilationData, is used to restore the Rules.
+     *
+     */
+    public void readExternal(final ObjectInput stream) throws IOException,
+                                                      ClassNotFoundException {
+        // PackageCompilationData must be restored before Rules as it has the ClassLoader needed to resolve the generated code references in Rules
+        this.packageCompilationData = (PackageCompilationData) stream.readObject();
+        this.name = (String) stream.readObject();
+        this.imports = (Map<String, ImportDeclaration>) stream.readObject();
+        this.staticImports = (Set) stream.readObject();
+        this.typeDeclarations = (Map<String, TypeDeclaration>) stream.readObject();
+        this.functions = (List) stream.readObject();
+        this.factTemplates = (Map) stream.readObject();
+        this.ruleFlows = (Map) stream.readObject();
+        this.globals = (Map) stream.readObject();
+        this.valid = stream.readBoolean();
+
+        // Return the rules stored as a byte[]
+        final byte[] bytes = (byte[]) stream.readObject();
+
+        //  Use a custom ObjectInputStream that can resolve against a given classLoader
+        final DroolsObjectInputStream streamWithLoader = new DroolsObjectInputStream( new ByteArrayInputStream( bytes ),
+                                                                                      this.packageCompilationData.getClassLoader() );
+
+        this.rules = (Map) streamWithLoader.readObject();
+    }
+
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+
+    /**
+     * Retrieve the name of this <code>Package</code>.
+     *
+     * @return The name of this <code>Package</code>.
+     */
+    public String getName() {
+        return this.name;
+    }
+
+    public void addImport(final ImportDeclaration importDecl) {
+        this.imports.put( importDecl.getTarget(), importDecl );
+    }
+
+    public void removeImport(final String importEntry) {
+        this.imports.remove( importEntry );
+    }
+
+    public Map<String, ImportDeclaration> getImports() {
+        return this.imports;
+    }
+    
+    public void addTypeDeclaration( final TypeDeclaration typeDecl ) {
+        this.typeDeclarations.put( typeDecl.getTypeName(), typeDecl );
+    }
+    
+    public void removeTypeDeclaration( final String type ) {
+        this.typeDeclarations.remove( type );
+    }
+    
+    public Map<String, TypeDeclaration> getTypeDeclarations() {
+        return this.typeDeclarations;
+    }
+    
+    public TypeDeclaration getTypeDeclaration( String type ) {
+        return this.typeDeclarations.get( type );
+    }
+
+    public void addStaticImport(final String functionImport) {
+        if ( this.staticImports == Collections.EMPTY_SET ) {
+            this.staticImports = new HashSet( 2 );
+        }
+        this.staticImports.add( functionImport );
+    }
+
+    public void addFunction(final String functionName) {
+        if ( this.functions == Collections.EMPTY_LIST ) {
+            this.functions = new ArrayList( 1 );
+        }
+
+        this.functions.add( functionName );
+    }
+
+    public List getFunctions() {
+        return this.functions;
+    }
+
+    public void removeFunctionImport(final String functionImport) {
+        this.staticImports.remove( functionImport );
+    }
+
+    public Set getStaticImports() {
+        return this.staticImports;
+    }
+
+    public void addGlobal(final String identifier,
+                          final Class clazz) {
+        if ( this.globals == Collections.EMPTY_MAP ) {
+            this.globals = new HashMap( 1 );
+        }
+        this.globals.put( identifier,
+                          clazz );
+    }
+
+    public void removeGlobal(final String identifier) {
+        this.globals.remove( identifier );
+    }
+
+    public Map getGlobals() {
+        return this.globals;
+    }
+
+    public PackageCompilationData removeFunction(final String functionName) {
+        if ( !this.functions.remove( functionName ) ) {
+            return null;
+        }
+        this.packageCompilationData.remove( this.name + "." + StringUtils.ucFirst( functionName ) );
+        return this.packageCompilationData;
+    }
+
+    public FactTemplate getFactTemplate(final String name) {
+        return (FactTemplate) this.factTemplates.get( name );
+    }
+
+    public void addFactTemplate(final FactTemplate factTemplate) {
+        if ( this.factTemplates == Collections.EMPTY_MAP ) {
+            this.factTemplates = new HashMap( 1 );
+        }
+        this.factTemplates.put( factTemplate.getName(),
+                                factTemplate );
+    }
+
+    /**
+     * Add a <code>Rule</code> to this <code>Package</code>.
+     *
+     * @param rule
+     *            The rule to add.
+     *
+     * @throws DuplicateRuleNameException
+     *             If the <code>Rule</code> attempting to be added has the
+     *             same name as another previously added <code>Rule</code>.
+     * @throws InvalidRuleException
+     *             If the <code>Rule</code> is not valid.
+     */
+    public void addRule(final Rule rule) {
+        final String name = rule.getName();
+
+        this.rules.put( name,
+                        rule );
+        rule.setLoadOrder( this.rules.size() );
+    }
+
+    /**
+     * Add a rule flow to this package.
+     */
+    public void addRuleFlow(Process process) {
+        if ( this.ruleFlows == Collections.EMPTY_MAP ) {
+            this.ruleFlows = new HashMap();
+        }
+        this.ruleFlows.put( process.getId(),
+                            process );
+    }
+
+    /**
+     * Get the rule flows for this package. The key is the ruleflow id.
+     * It will be Collections.EMPTY_MAP if none have been added.
+     */
+    public Map getRuleFlows() {
+        return this.ruleFlows;
+    }
+
+    /**
+     * Rule flows can be removed by ID.
+     */
+    public void removeRuleFlow(String id) {
+        if ( !this.ruleFlows.containsKey( id ) ) {
+            throw new IllegalArgumentException( "The rule flow with id [" + id + "] is not part of this package." );
+        }
+        this.ruleFlows.remove( id );
+    }
+
+    public PackageCompilationData removeRule(final Rule rule) {
+        this.rules.remove( rule.getName() );
+        final String consequenceName = rule.getConsequence().getClass().getName();
+
+        // check for compiled code and remove if present.
+        if ( this.packageCompilationData.remove( consequenceName ) ) {
+            removeClasses( rule.getLhs() );
+
+            // Now remove the rule class - the name is a subset of the consequence name
+            this.packageCompilationData.remove( consequenceName.substring( 0,
+                                                                           consequenceName.indexOf( "ConsequenceInvoker" ) ) );
+        }
+        return this.packageCompilationData;
+    }
+
+    private void removeClasses(final ConditionalElement ce) {
+        if ( ce instanceof GroupElement ) {
+            final GroupElement group = (GroupElement) ce;
+            for ( final Iterator it = group.getChildren().iterator(); it.hasNext(); ) {
+                final Object object = it.next();
+                if ( object instanceof ConditionalElement ) {
+                    removeClasses( (ConditionalElement) object );
+                } else if ( object instanceof Pattern ) {
+                    removeClasses( (Pattern) object );
+                }
+            }
+        } else if ( ce instanceof EvalCondition ) {
+            this.packageCompilationData.remove( ((EvalCondition) ce).getEvalExpression().getClass().getName() );
+        }
+    }
+
+    private void removeClasses(final Pattern pattern) {
+        for ( final Iterator it = pattern.getConstraints().iterator(); it.hasNext(); ) {
+            final Object object = it.next();
+            if ( object instanceof PredicateConstraint ) {
+                this.packageCompilationData.remove( ((PredicateConstraint) object).getPredicateExpression().getClass().getName() );
+            } else if ( object instanceof ReturnValueConstraint ) {
+                this.packageCompilationData.remove( ((ReturnValueConstraint) object).getExpression().getClass().getName() );
+            }
+        }
+    }
+
+    /**
+     * Retrieve a <code>Rule</code> by name.
+     *
+     * @param name
+     *            The name of the <code>Rule</code> to retrieve.
+     *
+     * @return The named <code>Rule</code>, or <code>null</code> if not
+     *         such <code>Rule</code> has been added to this
+     *         <code>Package</code>.
+     */
+    public Rule getRule(final String name) {
+        return (Rule) this.rules.get( name );
+    }
+
+    /**
+     * Retrieve all <code>Rules</code> in this <code>Package</code>.
+     *
+     * @return An array of all <code>Rules</code> in this <code>Package</code>.
+     */
+    public Rule[] getRules() {
+        return (Rule[]) this.rules.values().toArray( new Rule[this.rules.size()] );
+    }
+
+    public PackageCompilationData getPackageCompilationData() {
+        return this.packageCompilationData;
+    }
+
+    public String toString() {
+        return "[Package name=" + this.name + "]";
+    }
+
+    /** Once this is called, the package will be marked as invalid */
+    public void setError(final String summary) {
+        this.errorSummary = summary;
+        this.valid = false;
+    }
+
+    /**
+     * @return true (default) if there are no build/structural problems.
+     */
+    public boolean isValid() {
+        return this.valid;
+    }
+
+    /** This will throw an exception if the package is not valid */
+    public void checkValidity() {
+        if ( !isValid() ) {
+            throw new InvalidRulePackage( this.getErrorSummary() );
+        }
+    }
+
+    /**
+     * This will return the error summary (if any) if the package is invalid.
+     */
+    public String getErrorSummary() {
+        return this.errorSummary;
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof Package) ) {
+            return false;
+        }
+
+        final Package other = (Package) object;
+
+        return (this.name.equals( other.name ));
+    }
+
+    public int hashCode() {
+        return this.name.hashCode();
+    }
+    
+    /**
+     * Returns true if clazz is imported as an Event class in this package 
+     * @param clazz
+     * @return
+     */
+    public boolean isEvent( Class clazz ) {
+        if( clazz == null ) {
+            return false;
+        }
+        // check if clazz is resolved by any of the type declarations
+        for( TypeDeclaration type : this.typeDeclarations.values() ) {
+            if( type.matches( clazz ) && type.getRole() == TypeDeclaration.Role.EVENT ) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public void clear() {
+        this.rules.clear();
+        this.packageCompilationData.clear();
+        this.ruleFlows.clear();
+        this.imports.clear();
+        this.functions.clear();
+        this.staticImports.clear();
+        this.globals.clear();
+        this.factTemplates.clear();
+        this.typeDeclarations.clear();
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/PackageCompilationData.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/PackageCompilationData.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/PackageCompilationData.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,429 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.drools.CheckedDroolsException;
+import org.drools.RuntimeDroolsException;
+import org.drools.base.accumulators.JavaAccumulatorFunctionExecutor;
+import org.drools.common.DroolsObjectInputStream;
+import org.drools.spi.Accumulator;
+import org.drools.spi.Consequence;
+import org.drools.spi.EvalExpression;
+import org.drools.spi.PredicateExpression;
+import org.drools.spi.ReturnValueEvaluator;
+import org.drools.spi.ReturnValueExpression;
+import org.drools.workflow.core.node.ActionNode;
+import org.drools.workflow.instance.impl.ReturnValueConstraintEvaluator;
+
+public class PackageCompilationData
+    implements
+    Externalizable {
+
+    /**
+     *
+     */
+    private static final long             serialVersionUID = 400L;
+
+    private static final ProtectionDomain PROTECTION_DOMAIN;
+
+    private Map                           invokerLookups;
+
+    private Object                        AST;
+
+    private Map                           store;
+
+    private Map                           lineMappings;
+
+    private transient PackageClassLoader  classLoader;
+
+    private transient ClassLoader         parentClassLoader;
+    
+    private boolean                       dirty;
+
+    static {
+        PROTECTION_DOMAIN = (ProtectionDomain) AccessController.doPrivileged( new PrivilegedAction() {
+            public Object run() {
+                return PackageCompilationData.class.getProtectionDomain();
+            }
+        } );
+    }
+
+    /**
+     * Default constructor - for Externalizable. This should never be used by a user, as it
+     * will result in an invalid state for the instance.
+     */
+    public PackageCompilationData() {
+
+    }
+
+    public PackageCompilationData(final ClassLoader parentClassLoader) {
+        initClassLoader( parentClassLoader );
+        this.invokerLookups = new HashMap();
+        this.store = new HashMap();
+        this.lineMappings = new HashMap();
+        this.dirty = false;
+    }
+    
+    public boolean isDirty() {
+        return this.dirty;
+    }
+
+    private void initClassLoader(ClassLoader parentClassLoader) {
+        if ( parentClassLoader == null ) {
+            throw new RuntimeDroolsException( "PackageCompilationData cannot have a null parentClassLoader" );
+        }
+        this.parentClassLoader = parentClassLoader;
+        this.classLoader = new PackageClassLoader( this.parentClassLoader );
+    }
+
+    /**
+     * Handles the write serialization of the PackageCompilationData. Patterns in Rules may reference generated data which cannot be serialized by
+     * default methods. The PackageCompilationData holds a reference to the generated bytecode. The generated bytecode must be restored before any Rules.
+     *
+     */
+    public void writeExternal(final ObjectOutput stream) throws IOException {
+        stream.writeObject( this.store );
+        stream.writeObject( this.AST );
+
+        // Rules must be restored by an ObjectInputStream that can resolve using a given ClassLoader to handle seaprately by storing as
+        // a byte[]
+        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        final ObjectOutput out = new ObjectOutputStream( bos );
+        out.writeObject( this.invokerLookups );
+        stream.writeObject( bos.toByteArray() );
+    }
+
+    /**
+     * Handles the read serialization of the PackageCompilationData. Patterns in Rules may reference generated data which cannot be serialized by
+     * default methods. The PackageCompilationData holds a reference to the generated bytecode; which must be restored before any Rules.
+     * A custom ObjectInputStream, able to resolve classes against the bytecode, is used to restore the Rules.
+     *
+     */
+    public void readExternal(final ObjectInput stream) throws IOException,
+                                                      ClassNotFoundException {
+        if ( stream instanceof DroolsObjectInputStream ) {
+            DroolsObjectInputStream droolsStream = (DroolsObjectInputStream) stream;
+            initClassLoader( droolsStream.getClassLoader() );
+        } else {
+            initClassLoader( Thread.currentThread().getContextClassLoader() );
+        }
+
+        this.store = (Map) stream.readObject();
+        this.AST = stream.readObject();
+
+        // Return the rules stored as a byte[]
+        final byte[] bytes = (byte[]) stream.readObject();
+
+        //  Use a custom ObjectInputStream that can resolve against a given classLoader
+        final DroolsObjectInputStream streamWithLoader = new DroolsObjectInputStream( new ByteArrayInputStream( bytes ),
+                                                                                      this.classLoader );
+        this.invokerLookups = (Map) streamWithLoader.readObject();
+    }
+
+    public ClassLoader getClassLoader() {
+        return this.classLoader;
+    }
+
+    public byte[] read(final String resourceName) {
+        byte[] bytes = null;
+
+        if ( this.store != null ) {
+            bytes = ( byte[] ) this.store.get( resourceName );
+        }
+        return bytes;
+    }
+
+    public void write(final String resourceName,
+                      final byte[] clazzData) throws RuntimeDroolsException {
+        if ( this.store.put( resourceName,
+                             clazzData ) != null ) {
+            // we are updating an existing class so reload();
+            //reload();
+            this.dirty = true;
+        } else {
+            try {
+                wire( convertResourceToClassName( resourceName ) );
+            } catch ( final Exception e ) {
+                e.printStackTrace();
+                throw new RuntimeDroolsException( e );
+            }
+        }
+
+    }
+
+    public boolean remove(final String resourceName) throws RuntimeDroolsException {
+        this.invokerLookups.remove( resourceName );
+        if ( this.store.remove( convertClassToResourcePath( resourceName ) ) != null ) {
+            // we need to make sure the class is removed from the classLoader
+            // reload();
+            this.dirty = true;
+            return true;
+        }
+        return false;
+    }
+
+    public String[] list() {
+        if ( this.store == null ) {
+            return new String[0];
+        }
+        final List names = new ArrayList();
+
+        for ( final Iterator it = this.store.keySet().iterator(); it.hasNext(); ) {
+            final String name = (String) it.next();
+            names.add( name );
+        }
+
+        return (String[]) names.toArray( new String[this.store.size()] );
+    }
+
+    /**
+     * This class drops the classLoader and reloads it. During this process  it must re-wire all the invokeables.
+     * @throws CheckedDroolsException
+     */
+    public void reload() throws RuntimeDroolsException {
+        // drops the classLoader and adds a new one
+        this.classLoader = new PackageClassLoader( this.parentClassLoader );
+
+        // Wire up invokers
+        try {
+            for ( final Iterator it = this.invokerLookups.entrySet().iterator(); it.hasNext(); ) {
+                Entry entry = (Entry) it.next();
+                wire( (String) entry.getKey(),
+                      entry.getValue() );
+            }
+        } catch ( final ClassNotFoundException e ) {
+            throw new RuntimeDroolsException( e );
+        } catch ( final InstantiationError e ) {
+            throw new RuntimeDroolsException( e );
+        } catch ( final IllegalAccessException e ) {
+            throw new RuntimeDroolsException( e );
+        } catch ( final InstantiationException e ) {
+            throw new RuntimeDroolsException( e );
+        } finally {
+            this.dirty = false;
+        }
+    }
+
+    public void clear() {
+        this.store.clear();
+        this.invokerLookups.clear();
+        this.AST = null;
+        reload();
+    }
+
+    public void wire(final String className) throws ClassNotFoundException,
+                                            InstantiationException,
+                                            IllegalAccessException {
+        final Object invoker = this.invokerLookups.get( className );
+        wire( className,
+              invoker );
+    }
+
+    public void wire(final String className,
+                     final Object invoker) throws ClassNotFoundException,
+                                          InstantiationException,
+                                          IllegalAccessException {
+        final Class clazz = this.classLoader.findClass( className );
+        if ( invoker instanceof ReturnValueRestriction ) {
+            ((ReturnValueRestriction) invoker).setReturnValueExpression( (ReturnValueExpression) clazz.newInstance() );
+        } else if ( invoker instanceof PredicateConstraint ) {
+            ((PredicateConstraint) invoker).setPredicateExpression( (PredicateExpression) clazz.newInstance() );
+        } else if ( invoker instanceof EvalCondition ) {
+            ((EvalCondition) invoker).setEvalExpression( (EvalExpression) clazz.newInstance() );
+        } else if ( invoker instanceof Accumulate ) {
+            ((Accumulate) invoker).setAccumulator( (Accumulator) clazz.newInstance() );
+        } else if ( invoker instanceof Rule ) {
+            ((Rule) invoker).setConsequence( (Consequence) clazz.newInstance() );
+        } else if ( invoker instanceof JavaAccumulatorFunctionExecutor ) {
+            ((JavaAccumulatorFunctionExecutor) invoker).setExpression( (ReturnValueExpression) clazz.newInstance() );
+        } else if ( invoker instanceof ActionNode ) {
+            ((ActionNode) invoker).setAction( clazz.newInstance() );
+        } else if ( invoker instanceof ReturnValueConstraintEvaluator ) {
+            ((ReturnValueConstraintEvaluator) invoker).setEvaluator( (ReturnValueEvaluator) clazz.newInstance() );
+        }
+    }
+
+    public String toString() {
+        return this.getClass().getName() + this.store.toString();
+    }
+
+    public void putInvoker(final String className,
+                           final Object invoker) {
+        this.invokerLookups.put( className,
+                                 invoker );
+    }
+
+    public void putAllInvokers(final Map invokers) {
+        this.invokerLookups.putAll( invokers );
+
+    }
+
+    public Map getInvokers() {
+        return this.invokerLookups;
+    }
+
+    public void removeInvoker(final String className) {
+        this.invokerLookups.remove( className );
+    }
+
+    public Map getLineMappings() {
+        if ( this.lineMappings == null ) {
+            this.lineMappings = new HashMap();
+        }
+        return this.lineMappings;
+    }
+
+    public LineMappings getLineMappings(final String className) {
+        return (LineMappings) getLineMappings().get( className );
+    }
+
+    public Object getAST() {
+        return this.AST;
+    }
+
+    public void setAST(final Object ast) {
+        this.AST = ast;
+    }
+
+    /**
+     * Lifted and adapted from Jakarta commons-jci
+     *
+     * @author mproctor
+     *
+     */
+    public class PackageClassLoader extends ClassLoader
+        implements
+        DroolsClassLoader {
+
+        public PackageClassLoader(final ClassLoader parentClassLoader) {
+            super( parentClassLoader );
+        }
+
+        public Class fastFindClass(final String name) {
+            final Class clazz = findLoadedClass( name );
+
+            if ( clazz == null ) {
+                final byte[] clazzBytes = read( convertClassToResourcePath( name ) );
+                if ( clazzBytes != null ) {
+                    return defineClass( name,
+                                        clazzBytes,
+                                        0,
+                                        clazzBytes.length,
+                                        PROTECTION_DOMAIN );
+                }
+            }
+
+            return clazz;
+        }
+
+        /**
+         * Javadocs recommend that this method not be overloaded. We overload this so that we can prioritise the fastFindClass
+         * over method calls to parent.loadClass(name, false); and c = findBootstrapClass0(name); which the default implementation
+         * would first - hence why we call it "fastFindClass" instead of standard findClass, this indicates that we give it a
+         * higher priority than normal.
+         *
+         */
+        protected synchronized Class loadClass(final String name,
+                                               final boolean resolve) throws ClassNotFoundException {
+            Class clazz = fastFindClass( name );
+
+            if ( clazz == null ) {
+                final ClassLoader parent = getParent();
+                if ( parent != null ) {
+                    clazz = parent.loadClass( name );
+                } else {
+                    throw new ClassNotFoundException( name );
+                }
+            }
+
+            if ( resolve ) {
+                resolveClass( clazz );
+            }
+
+            return clazz;
+        }
+
+        protected Class findClass(final String name) throws ClassNotFoundException {
+            final Class clazz = fastFindClass( name );
+            if ( clazz == null ) {
+                throw new ClassNotFoundException( name );
+            }
+            return clazz;
+        }
+
+        public InputStream getResourceAsStream(final String name) {
+            final byte[] bytes = (byte[]) PackageCompilationData.this.store.get( name );
+            if ( bytes != null ) {
+                return new ByteArrayInputStream( bytes );
+            } else {
+                InputStream input = this.getParent().getResourceAsStream( name );
+                if ( input == null ) {
+                    input = super.getResourceAsStream( name );
+                }
+                return input;
+            }
+        }
+    }
+
+    /**
+     * Please do not use - internal
+     * org/my/Class.xxx -> org.my.Class
+     */
+    public static String convertResourceToClassName(final String pResourceName) {
+        return stripExtension( pResourceName ).replace( '/',
+                                                        '.' );
+    }
+
+    /**
+     * Please do not use - internal
+     * org.my.Class -> org/my/Class.class
+     */
+    public static String convertClassToResourcePath(final String pName) {
+        return pName.replace( '.',
+                              '/' ) + ".class";
+    }
+
+    /**
+     * Please do not use - internal
+     * org/my/Class.xxx -> org/my/Class
+     */
+    public static String stripExtension(final String pResourceName) {
+        final int i = pResourceName.lastIndexOf( '.' );
+        final String withoutExtension = pResourceName.substring( 0,
+                                                                 i );
+        return withoutExtension;
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Pattern.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Pattern.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Pattern.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,271 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.spi.Constraint;
+import org.drools.spi.Extractor;
+import org.drools.spi.ObjectType;
+import org.drools.spi.PatternExtractor;
+
+public class Pattern
+    implements
+    RuleConditionElement {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+    private final ObjectType  objectType;
+    private List              constraints      = Collections.EMPTY_LIST;
+    final Declaration         declaration;
+    private Map               declarations;
+    private final int         index;
+    private PatternSource     source;
+
+    // this is the offset of the related fact inside a tuple. i.e:
+    // the position of the related fact inside the tuple; 
+    private int               offset;
+
+    public Pattern(final int index,
+                   final ObjectType objectType) {
+        this( index,
+              index,
+              objectType,
+              null );
+    }
+
+    public Pattern(final int index,
+                   final ObjectType objectType,
+                   final String identifier) {
+        this( index,
+              index,
+              objectType,
+              identifier );
+    }
+
+    public Pattern(final int index,
+                   final int offset,
+                   final ObjectType objectType,
+                   final String identifier) {
+        this( index,
+              offset,
+              objectType,
+              identifier,
+              false );
+    }
+
+    public Pattern(final int index,
+                   final int offset,
+                   final ObjectType objectType,
+                   final String identifier,
+                   final boolean isInternalFact) {
+        this.index = index;
+        this.offset = offset;
+        this.objectType = objectType;
+        if ( identifier != null && (!identifier.equals( "" )) ) {
+            this.declaration = new Declaration( identifier,
+                                                new PatternExtractor( objectType ),
+                                                this,
+                                                isInternalFact );
+            this.declarations = new HashMap( 2 ); // default to avoid immediate resize
+            this.declarations.put( this.declaration.getIdentifier(),
+                                   this.declaration );
+        } else {
+            this.declaration = null;
+        }
+    }
+
+    public Object clone() {
+        final String identifier = (this.declaration != null) ? this.declaration.getIdentifier() : null;
+        final Pattern clone = new Pattern( this.index,
+                                           this.offset,
+                                           this.objectType,
+                                           identifier,
+                                           this.declaration != null ? this.declaration.isInternalFact() : false );
+        if( this.getSource() != null ) {
+            clone.setSource( (PatternSource) this.getSource().clone() );
+        }
+
+        for ( final Iterator it = this.constraints.iterator(); it.hasNext(); ) {
+            final Object constr = it.next();
+            if ( constr instanceof Declaration ) {
+                final Declaration decl = (Declaration) constr;
+                clone.addDeclaration( decl.getIdentifier(),
+                                      decl.getExtractor() );
+            } else {
+                Constraint constraint = (Constraint) ((Constraint) constr).clone();
+                
+                // we must update pattern references in cloned declarations
+                Declaration[] oldDecl = ((Constraint) constr).getRequiredDeclarations();
+                Declaration[] newDecl = constraint.getRequiredDeclarations();
+                for( int i = 0; i < newDecl.length; i++ ) {
+                    if( newDecl[i].getPattern() == this ) {
+                        newDecl[i].setPattern( clone );
+                        // we still need to call replace because there might be nested declarations to replace
+                        constraint.replaceDeclaration( oldDecl[i], newDecl[i] );
+                    }
+                }
+                
+                clone.addConstraint( constraint );
+            }
+        }
+        return clone;
+    }
+
+    public ObjectType getObjectType() {
+        return this.objectType;
+    }
+
+    public PatternSource getSource() {
+        return source;
+    }
+
+    public void setSource(PatternSource source) {
+        this.source = source;
+    }
+
+    public List getConstraints() {
+        return Collections.unmodifiableList( this.constraints );
+    }
+
+    public void addConstraint(final Constraint constraint) {
+        if ( this.constraints == Collections.EMPTY_LIST ) {
+            this.constraints = new ArrayList( 1 );
+        }
+        this.constraints.add( constraint );
+    }
+
+    public Declaration addDeclaration(final String identifier,
+                                      final Extractor extractor) {
+        if ( this.constraints == Collections.EMPTY_LIST ) {
+            this.constraints = new ArrayList( 1 );
+        }
+        final Declaration declaration = new Declaration( identifier,
+                                                         extractor,
+                                                         this );
+        this.constraints.add( declaration );
+        if ( this.declarations == null ) {
+            this.declarations = new HashMap( 2 ); // default to avoid immediate resize
+        }
+        this.declarations.put( declaration.getIdentifier(),
+                               declaration );
+        return declaration;
+
+    }
+
+    public boolean isBound() {
+        return (this.declaration != null);
+    }
+
+    public Declaration getDeclaration() {
+        return this.declaration;
+    }
+
+    public int getIndex() {
+        return this.index;
+    }
+
+    /**
+     * The offset of the fact related to this pattern 
+     * inside the tuple
+     * 
+     * @return the offset
+     */
+    public int getOffset() {
+        return this.offset;
+    }
+
+    public void setOffset(final int offset) {
+        this.offset = offset;
+    }
+
+    public Map getInnerDeclarations() {
+        return (this.declarations != null) ? this.declarations : Collections.EMPTY_MAP;
+    }
+
+    public Map getOuterDeclarations() {
+        return (this.declarations != null) ? this.declarations : Collections.EMPTY_MAP;
+    }
+
+    public Declaration resolveDeclaration(final String identifier) {
+        return (this.declarations != null) ? (Declaration) this.declarations.get( identifier ) : null;
+    }
+
+    public String toString() {
+        return "Pattern type='" + ((this.objectType == null) ? "null" : this.objectType.toString()) + "', index='" + this.index + "', offset='" + this.getOffset() + "', identifer='" + ((this.declaration == null) ? "" : this.declaration.toString())
+               + "'";
+    }
+
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + this.constraints.hashCode();
+        result = PRIME * result + ((this.declaration == null) ? 0 : this.declaration.hashCode());
+        result = PRIME * result + this.index;
+        result = PRIME * result + ((this.objectType == null) ? 0 : this.objectType.hashCode());
+        result = PRIME * result + this.offset;
+        result = PRIME * result + ((this.source == null) ? 0 : this.source.hashCode());
+        return result;
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || getClass() != object.getClass() ) {
+            return false;
+        }
+
+        final Pattern other = (Pattern) object;
+
+        if ( !this.constraints.equals( other.constraints ) ) {
+            return false;
+        }
+
+        if ( this.declaration == null ) {
+            if ( other.declaration != null ) {
+                return false;
+            }
+        } else if ( !this.declaration.equals( other.declaration ) ) {
+            return false;
+        }
+
+        if ( this.index != other.index ) {
+            return false;
+        }
+
+        if ( !this.objectType.equals( other.objectType ) ) {
+            return false;
+        }
+        if ( this.offset != other.offset ) {
+            return false;
+        }
+        return (this.source == null) ? other.source == null : this.source.equals( other.source );
+    }
+
+    public List getNestedElements() {
+        return this.source != null ? Collections.singletonList( this.source ) : Collections.EMPTY_LIST;
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/PatternSource.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/PatternSource.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/PatternSource.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Jun 25, 2007
+ */
+package org.drools.rule;
+
+/**
+ * A markup interface for pattern source elements
+ * 
+ * @author etirelli
+ */
+public interface PatternSource extends RuleConditionElement {
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/PredicateConstraint.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/PredicateConstraint.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/PredicateConstraint.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,328 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Arrays;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.spi.Extractor;
+import org.drools.spi.PredicateExpression;
+import org.drools.spi.Restriction;
+
+/**
+ * A predicate can be written as a top level constraint or be nested
+ * inside inside a field constraint (and as so, must implement the 
+ * Restriction interface).
+ * 
+ * @author etirelli
+ */
+public class PredicateConstraint
+    implements
+    BetaNodeFieldConstraint,
+    AlphaNodeFieldConstraint,
+    Restriction {
+
+    /**
+     * 
+     */
+    private static final long          serialVersionUID   = 400L;
+
+    private PredicateExpression        expression;
+
+    private final Declaration[]        requiredDeclarations;
+
+    private final Declaration[]        previousDeclarations;
+
+    private final Declaration[]        localDeclarations;
+
+    private final String[]             requiredGlobals;
+
+    private static final Declaration[] EMPTY_DECLARATIONS = new Declaration[0];
+    private static final String[]      EMPTY_GLOBALS      = new String[0];
+
+    public PredicateConstraint(final PredicateExpression evaluator) {
+        this( evaluator,
+              null,
+              null,
+              null );
+    }
+
+    public PredicateConstraint(final Declaration[] previousDeclarations,
+                               final Declaration[] localDeclarations) {
+        this( null,
+              previousDeclarations,
+              localDeclarations,
+              null );
+    }
+
+    public PredicateConstraint(final PredicateExpression expression,
+                               final Declaration[] previousDeclarations,
+                               final Declaration[] localDeclarations,
+                               final String[] requiredGlobals) {
+
+        this.expression = expression;
+
+        if ( previousDeclarations == null ) {
+            this.previousDeclarations = PredicateConstraint.EMPTY_DECLARATIONS;
+        } else {
+            this.previousDeclarations = previousDeclarations;
+        }
+
+        if ( localDeclarations == null ) {
+            this.localDeclarations = PredicateConstraint.EMPTY_DECLARATIONS;
+        } else {
+            this.localDeclarations = localDeclarations;
+        }
+
+        if ( requiredGlobals == null ) {
+            this.requiredGlobals = PredicateConstraint.EMPTY_GLOBALS;
+        } else {
+            this.requiredGlobals = requiredGlobals;
+        }
+
+        this.requiredDeclarations = new Declaration[this.previousDeclarations.length + this.localDeclarations.length];
+        System.arraycopy( this.previousDeclarations,
+                          0,
+                          this.requiredDeclarations,
+                          0,
+                          this.previousDeclarations.length );
+        System.arraycopy( this.localDeclarations,
+                          0,
+                          this.requiredDeclarations,
+                          this.previousDeclarations.length,
+                          this.localDeclarations.length );
+    }
+
+    public Declaration[] getRequiredDeclarations() {
+        return this.requiredDeclarations;
+    }
+
+    public Declaration[] getPreviousDeclarations() {
+        return this.previousDeclarations;
+    }
+
+    public Declaration[] getLocalDeclarations() {
+        return this.localDeclarations;
+    }
+
+    public void replaceDeclaration(Declaration oldDecl,
+                                   Declaration newDecl) {
+        for ( int i = 0; i < this.requiredDeclarations.length; i++ ) {
+            if ( this.requiredDeclarations[i].equals( oldDecl ) ) {
+                this.requiredDeclarations[i] = newDecl;
+            }
+        }
+        for ( int i = 0; i < this.previousDeclarations.length; i++ ) {
+            if ( this.previousDeclarations[i].equals( oldDecl ) ) {
+                this.previousDeclarations[i] = newDecl;
+            }
+        }
+        for ( int i = 0; i < this.localDeclarations.length; i++ ) {
+            if ( this.localDeclarations[i].equals( oldDecl ) ) {
+                this.localDeclarations[i] = newDecl;
+            }
+        }
+    }
+
+    public void setPredicateExpression(final PredicateExpression expression) {
+        this.expression = expression;
+    }
+
+    public PredicateExpression getPredicateExpression() {
+        return this.expression;
+    }
+
+    public String toString() {
+        return "[PredicateConstraint previousDeclarations=" + this.previousDeclarations + " localDeclarations=" + this.localDeclarations + "]";
+    }
+
+    public int hashCode() {
+        return this.expression.hashCode();
+    }
+
+    public boolean equals(final Object object) {
+        if ( object == this ) {
+            return true;
+        }
+
+        if ( object == null || object.getClass() != PredicateConstraint.class ) {
+            return false;
+        }
+
+        final PredicateConstraint other = (PredicateConstraint) object;
+
+        if ( this.previousDeclarations.length != other.previousDeclarations.length ) {
+            return false;
+        }
+
+        if ( this.localDeclarations.length != other.localDeclarations.length ) {
+            return false;
+        }
+
+        if ( this.requiredGlobals.length != other.requiredGlobals.length ) {
+            return false;
+        }
+
+        for ( int i = 0, length = this.previousDeclarations.length; i < length; i++ ) {
+            if ( this.previousDeclarations[i].getPattern().getOffset() != other.previousDeclarations[i].getPattern().getOffset() ) {
+                return false;
+            }
+
+            if ( !this.previousDeclarations[i].getExtractor().equals( other.previousDeclarations[i].getExtractor() ) ) {
+                return false;
+            }
+        }
+
+        for ( int i = 0, length = this.localDeclarations.length; i < length; i++ ) {
+            if ( this.localDeclarations[i].getPattern().getOffset() != other.localDeclarations[i].getPattern().getOffset() ) {
+                return false;
+            }
+
+            if ( !this.localDeclarations[i].getExtractor().equals( other.localDeclarations[i].getExtractor() ) ) {
+                return false;
+            }
+        }
+
+        if ( !Arrays.equals( this.requiredGlobals,
+                             other.requiredGlobals ) ) {
+            return false;
+        }
+
+        return this.expression.equals( other.expression );
+    }
+
+    public ContextEntry getContextEntry() {
+        return new PredicateContextEntry();
+    }
+
+    public boolean isAllowed(final InternalFactHandle handle,
+                             final InternalWorkingMemory workingMemory) {
+        try {
+            return this.expression.evaluate( handle.getObject(),
+                                             null,
+                                             this.previousDeclarations,
+                                             this.localDeclarations,
+                                             workingMemory );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( "Exception executing predicate " + this.expression,
+                                              e );
+        }
+    }
+
+    public boolean isAllowed(Extractor extractor,
+                             InternalFactHandle handle,
+                             InternalWorkingMemory workingMemory) {
+        throw new UnsupportedOperationException("Method not supported. Please contact development team.");
+    }
+
+    public boolean isAllowedCachedLeft(final ContextEntry context,
+                                       final InternalFactHandle handle) {
+        try {
+            final PredicateContextEntry ctx = (PredicateContextEntry) context;
+            return this.expression.evaluate( handle.getObject(),
+                                             ctx.leftTuple,
+                                             this.previousDeclarations,
+                                             this.localDeclarations,
+                                             ctx.workingMemory );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( "Exception executing predicate " + this.expression,
+                                              e );
+        }
+    }
+
+    public boolean isAllowedCachedRight(final ReteTuple tuple,
+                                        final ContextEntry context) {
+        try {
+            final PredicateContextEntry ctx = (PredicateContextEntry) context;
+            return this.expression.evaluate( ctx.rightObject,
+                                             tuple,
+                                             this.previousDeclarations,
+                                             this.localDeclarations,
+                                             ctx.workingMemory );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( "Exception executing predicate " + this.expression,
+                                              e );
+        }
+    }
+
+    public Object clone() {
+        Declaration[] previous = new Declaration[this.previousDeclarations.length];
+        for ( int i = 0; i < previous.length; i++ ) {
+            previous[i] = (Declaration) this.previousDeclarations[i].clone();
+        }
+
+        Declaration[] local = new Declaration[this.localDeclarations.length];
+        for ( int i = 0; i < local.length; i++ ) {
+            local[i] = (Declaration) this.localDeclarations[i].clone();
+        }
+
+        return new PredicateConstraint( this.expression,
+                                        previous,
+                                        local,
+                                        this.requiredGlobals );
+    }
+
+    public static class PredicateContextEntry
+        implements
+        ContextEntry {
+
+        private static final long    serialVersionUID = 400L;
+
+        public ReteTuple             leftTuple;
+        public Object                rightObject;
+        public InternalWorkingMemory workingMemory;
+
+        private ContextEntry         entry;
+
+        public PredicateContextEntry() {
+        }
+
+        public ContextEntry getNext() {
+            return this.entry;
+        }
+
+        public void setNext(final ContextEntry entry) {
+            this.entry = entry;
+        }
+
+        public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
+                                         final InternalFactHandle handle) {
+            this.workingMemory = workingMemory;
+            this.rightObject = handle.getObject();
+        }
+
+        public void updateFromTuple(final InternalWorkingMemory workingMemory,
+                                    final ReteTuple tuple) {
+            this.workingMemory = workingMemory;
+            this.leftTuple = tuple;
+        }
+        
+        public void resetTuple() {
+            this.leftTuple = null;
+        }
+        
+        public void resetFactHandle() {
+            this.rightObject = null;
+        }        
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Query.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Query.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Query.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,38 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Query extends Rule {    
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    public Query(final String name) {
+        super( name );
+    }    
+
+    /** 
+     * Override this as Queries will NEVER have a consequence, and it should
+     * not be taken into account when deciding if it is valid.
+     */
+    public boolean isValid() {
+        return super.isSemanticallyValid();
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/ReturnValueConstraint.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/ReturnValueConstraint.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/ReturnValueConstraint.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,146 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.RuntimeDroolsException;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.rule.ReturnValueRestriction.ReturnValueContextEntry;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.ReturnValueExpression;
+
+public class ReturnValueConstraint
+    implements
+    BetaNodeFieldConstraint,
+    AlphaNodeFieldConstraint {
+
+    /**
+     * 
+     */
+    private static final long            serialVersionUID = 400L;
+
+    private final FieldExtractor         fieldExtractor;
+    private final ReturnValueRestriction restriction;
+
+    public ReturnValueConstraint(final FieldExtractor fieldExtractor,
+                                 final ReturnValueRestriction restriction) {
+        this.fieldExtractor = fieldExtractor;
+        this.restriction = restriction;
+    }
+
+    public Declaration[] getRequiredDeclarations() {
+        return this.restriction.getRequiredDeclarations();
+    }
+
+    public void replaceDeclaration(Declaration oldDecl,
+                                   Declaration newDecl) {
+        this.restriction.replaceDeclaration( oldDecl,
+                                             newDecl );
+    }
+    
+    public void setReturnValueExpression(final ReturnValueExpression expression) {
+        this.restriction.setReturnValueExpression( expression );
+    }
+
+    public ReturnValueExpression getExpression() {
+        return this.restriction.getExpression();
+    }
+
+    public Evaluator getEvaluator() {
+        return this.restriction.getEvaluator();
+    }
+
+    public String toString() {
+        return "[ReturnValueConstraint fieldExtractor=" + this.fieldExtractor + " evaluator=" + getEvaluator() + " declarations=" + getRequiredDeclarations() + "]";
+    }
+
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + this.fieldExtractor.hashCode();
+        result = PRIME * result + this.restriction.hashCode();
+        return result;
+    }
+
+    public boolean equals(final Object object) {
+        if ( object == this ) {
+            return true;
+        }
+
+        if ( object == null || object.getClass() != ReturnValueConstraint.class ) {
+            return false;
+        }
+
+        final ReturnValueConstraint other = (ReturnValueConstraint) object;
+
+        return this.fieldExtractor.equals( other.fieldExtractor ) && this.restriction.equals( other.restriction );
+    }
+
+    public ContextEntry getContextEntry() {
+        return this.restriction.getContextEntry();
+    }
+
+    public boolean isAllowed(final InternalFactHandle handle,
+                             final InternalWorkingMemory workingMemory) {
+        try {
+            return this.restriction.isAllowed( this.fieldExtractor,
+                                               handle,
+                                               null,
+                                               workingMemory );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( "Exception executing ReturnValue constraint " + this.restriction + " : " + e.getMessage(),
+                                              e );
+        }
+    }
+
+    public boolean isAllowedCachedLeft(final ContextEntry context,
+                                       final InternalFactHandle handle) {
+        try {
+            final ReturnValueContextEntry ctx = (ReturnValueContextEntry) context;
+            return this.restriction.isAllowed( this.fieldExtractor,
+                                               handle,
+                                               ctx.getTuple(),
+                                               ctx.getWorkingMemory() );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( "Exception executing ReturnValue constraint " + this.restriction + " : " + e.getMessage(),
+                                              e );
+        }
+    }
+
+    public boolean isAllowedCachedRight(final ReteTuple tuple,
+                                        final ContextEntry context) {
+        try {
+            final ReturnValueContextEntry ctx = (ReturnValueContextEntry) context;
+            return this.restriction.isAllowed( this.fieldExtractor,
+                                               ctx.getHandle(),
+                                               tuple,
+                                               ctx.getWorkingMemory() );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( "Exception executing ReturnValue constraint " + this.restriction + " : " + e.getMessage(),
+                                              e );
+        }
+    }
+    
+    public Object clone() {
+        return new ReturnValueConstraint( this.fieldExtractor, (ReturnValueRestriction) this.restriction.clone() );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/ReturnValueRestriction.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/ReturnValueRestriction.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/ReturnValueRestriction.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,371 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Arrays;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.WorkingMemory;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.Restriction;
+import org.drools.spi.ReturnValueExpression;
+import org.drools.spi.Tuple;
+
+public class ReturnValueRestriction
+    implements
+    Restriction {
+
+    private static final long             serialVersionUID = 400L;
+
+    private ReturnValueExpression         expression;
+
+    private final Declaration[]           requiredDeclarations;
+    
+    private final String[]                requiredGlobals;
+
+    private final Declaration[]           previousDeclarations;
+
+    private final Declaration[]           localDeclarations;
+
+    private final Evaluator               evaluator;
+
+    private static final Declaration[]    noRequiredDeclarations = new Declaration[]{};
+
+    private static final String[]         noRequiredGlobals = new String[]{};
+
+    private final ReturnValueContextEntry contextEntry;
+
+    public ReturnValueRestriction(final FieldExtractor fieldExtractor,
+                                  final Declaration[] previousDeclarations,
+                                  final Declaration[] localDeclarations,
+                                  final String[] requiredGlobals,
+                                  final Evaluator evaluator) {
+        this( fieldExtractor,
+              null,
+              previousDeclarations,
+              localDeclarations,
+              requiredGlobals,
+              evaluator );
+    }
+
+    public ReturnValueRestriction(final FieldExtractor fieldExtractor,
+                                  final ReturnValueExpression returnValueExpression,
+                                  final Declaration[] previousDeclarations,
+                                  final Declaration[] localDeclarations,
+                                  final String[] requiredGlobals,
+                                  final Evaluator evaluator) {
+        this.expression = returnValueExpression;
+
+        if ( previousDeclarations != null ) {
+            this.previousDeclarations = previousDeclarations;
+        } else {
+            this.previousDeclarations = ReturnValueRestriction.noRequiredDeclarations;
+        }
+
+        if ( localDeclarations != null ) {
+            this.localDeclarations = localDeclarations;
+        } else {
+            this.localDeclarations = ReturnValueRestriction.noRequiredDeclarations;
+        }
+        
+        if ( requiredGlobals != null ) {
+            this.requiredGlobals = requiredGlobals;
+        } else {
+            this.requiredGlobals = ReturnValueRestriction.noRequiredGlobals;
+        }
+
+        this.evaluator = evaluator;
+        this.contextEntry = new ReturnValueContextEntry( fieldExtractor,
+                                                         this.previousDeclarations,
+                                                         this.localDeclarations );
+
+        this.requiredDeclarations = new Declaration[this.previousDeclarations.length + this.localDeclarations.length];
+        System.arraycopy( this.previousDeclarations,
+                          0,
+                          this.requiredDeclarations,
+                          0,
+                          this.previousDeclarations.length );
+        System.arraycopy( this.localDeclarations,
+                          0,
+                          this.requiredDeclarations,
+                          this.previousDeclarations.length,
+                          this.localDeclarations.length );
+    }
+
+    public Declaration[] getRequiredDeclarations() {
+        return this.requiredDeclarations;
+    }
+
+    public Declaration[] getPreviousDeclarations() {
+        return this.previousDeclarations;
+    }
+
+    public Declaration[] getLocalDeclarations() {
+        return this.localDeclarations;
+    }
+    
+    public String[] getRequiredGlobals() {
+        return this.requiredGlobals;
+    }
+    
+    public void replaceDeclaration(Declaration oldDecl,
+                                   Declaration newDecl) {
+        for( int i = 0; i < this.requiredDeclarations.length; i++) {
+            if( this.requiredDeclarations[i].equals( oldDecl ) ) {
+                this.requiredDeclarations[i] = newDecl;
+            }
+        }
+        for( int i = 0; i < this.previousDeclarations.length; i++) {
+            if( this.previousDeclarations[i].equals( oldDecl ) ) {
+                this.previousDeclarations[i] = newDecl;
+            }
+        }
+        for( int i = 0; i < this.localDeclarations.length; i++) {
+            if( this.localDeclarations[i].equals( oldDecl ) )  {
+                this.localDeclarations[i] = newDecl;
+            }
+        }
+    }
+
+    public void setReturnValueExpression(final ReturnValueExpression expression) {
+        this.expression = expression;
+    }
+
+    public ReturnValueExpression getExpression() {
+        return this.expression;
+    }
+
+    public Evaluator getEvaluator() {
+        return this.evaluator;
+    }
+
+    public boolean isAllowed(final Extractor extractor,
+                             final InternalFactHandle handle,
+                             final Tuple tuple,
+                             final WorkingMemory workingMemory) {
+        try {
+            return this.evaluator.evaluate( null,
+                                            extractor,
+                                            handle.getObject(), this.expression.evaluate( handle.getObject(),
+                                                                                              tuple,
+                                                                                              this.previousDeclarations,
+                                                                                              this.localDeclarations,
+                                                                                              workingMemory ) );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( e );
+        }
+    }
+
+    public boolean isAllowed(final Extractor extractor,
+                             final InternalFactHandle handle,
+                             final InternalWorkingMemory workingMemoiry) {
+        throw new UnsupportedOperationException( "does not support method call isAllowed(Object object, InternalWorkingMemory workingMemoiry)" );
+    }
+
+    public boolean isAllowedCachedLeft(final ContextEntry context,
+                                       final InternalFactHandle handle) {
+        throw new UnsupportedOperationException( "does not support method call isAllowed(Object object, InternalWorkingMemory workingMemoiry)" );
+    }
+
+    public boolean isAllowedCachedRight(final ReteTuple tuple,
+                                        final ContextEntry context) {
+        throw new UnsupportedOperationException( "does not support method call isAllowed(Object object, InternalWorkingMemory workingMemoiry)" );
+    }
+
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + this.evaluator.hashCode();
+        result = PRIME * result + ((this.expression != null) ? this.expression.hashCode() : 0);
+        result = PRIME * result + ReturnValueRestriction.hashCode( this.localDeclarations );
+        result = PRIME * result + ReturnValueRestriction.hashCode( this.previousDeclarations );
+        result = PRIME * result + ReturnValueRestriction.hashCode( this.requiredGlobals );
+        return result;
+    }
+
+    public boolean equals(final Object object) {
+        if ( object == this ) {
+            return true;
+        }
+
+        if ( object == null || object.getClass() != ReturnValueRestriction.class ) {
+            return false;
+        }
+
+        final ReturnValueRestriction other = (ReturnValueRestriction) object;
+
+        if ( this.localDeclarations.length != other.localDeclarations.length ) {
+            return false;
+        }
+
+        if ( this.previousDeclarations.length != other.previousDeclarations.length ) {
+            return false;
+        }
+
+        if ( this.requiredGlobals.length != other.requiredGlobals.length ) {
+            return false;
+        }
+
+        if ( !Arrays.equals( this.localDeclarations,
+                             other.localDeclarations ) ) {
+            return false;
+        }
+
+        if ( !Arrays.equals( this.previousDeclarations,
+                             other.previousDeclarations ) ) {
+            return false;
+        }
+
+        if ( !Arrays.equals( this.requiredGlobals,
+                             other.requiredGlobals ) ) {
+            return false;
+        }
+
+        return this.evaluator.equals( other.evaluator ) && this.expression.equals( other.expression );
+    }
+
+    private static int hashCode(final Object[] array) {
+        final int PRIME = 31;
+        if ( array == null ) {
+            return 0;
+        }
+        int result = 1;
+        for ( int index = 0; index < array.length; index++ ) {
+            result = PRIME * result + (array[index] == null ? 0 : array[index].hashCode());
+        }
+        return result;
+    }
+
+    public ContextEntry getContextEntry() {
+        return this.contextEntry;
+    }
+    
+    public Object clone() {
+        Declaration[] previous = new Declaration[ this.previousDeclarations.length ];
+        for( int i = 0; i < previous.length; i++ ) {
+            previous[i] = (Declaration) this.previousDeclarations[i].clone();
+        }
+        
+        Declaration[] local = new Declaration[ this.localDeclarations.length ];
+        for( int i = 0; i < local.length; i++ ) {
+            local[i] = (Declaration) this.localDeclarations[i].clone();
+        }
+        
+        return new ReturnValueRestriction( this.contextEntry.fieldExtractor,
+                                           previous,
+                                           local,
+                                           this.requiredGlobals,
+                                           this.evaluator );
+    }
+
+    public static class ReturnValueContextEntry
+        implements
+        ContextEntry {
+
+        private static final long    serialVersionUID = 400L;
+
+        public FieldExtractor        fieldExtractor;
+        public InternalFactHandle    handle;
+        public ReteTuple             leftTuple;
+        public InternalWorkingMemory workingMemory;
+        public Declaration[]         previousDeclarations;
+        public Declaration[]         localDeclarations;
+
+        private ContextEntry         entry;
+
+        public ReturnValueContextEntry(final FieldExtractor fieldExtractor,
+                                       final Declaration[] previousDeclarations,
+                                       final Declaration[] localDeclarations) {
+            this.fieldExtractor = fieldExtractor;
+            this.previousDeclarations = previousDeclarations;
+            this.localDeclarations = localDeclarations;
+        }
+
+        public ContextEntry getNext() {
+            return this.entry;
+        }
+
+        public void setNext(final ContextEntry entry) {
+            this.entry = entry;
+        }
+
+        public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
+                                         final InternalFactHandle handle) {
+            this.workingMemory = workingMemory;
+            this.handle = handle;
+        }
+
+        public void updateFromTuple(final InternalWorkingMemory workingMemory,
+                                    final ReteTuple tuple) {
+            this.workingMemory = workingMemory;
+            this.leftTuple = tuple;
+        }
+
+        /* (non-Javadoc)
+         * @see org.drools.rule.ReturnValueContextEntry#getFieldExtractor()
+         */
+        public FieldExtractor getFieldExtractor() {
+            return this.fieldExtractor;
+        }
+
+        /* (non-Javadoc)
+         * @see org.drools.rule.ReturnValueContextEntry#getTuple()
+         */
+        public ReteTuple getTuple() {
+            return this.leftTuple;
+        }
+
+        /* (non-Javadoc)
+         * @see org.drools.rule.ReturnValueContextEntry#getObject()
+         */
+        public InternalFactHandle getHandle() {
+            return this.handle;
+        }
+
+        /* (non-Javadoc)
+         * @see org.drools.rule.ReturnValueContextEntry#getRequiredDeclarations()
+         */
+        public Declaration[] getPreviousDeclarations() {
+            return this.previousDeclarations;
+        }
+
+        public Declaration[] getLocalDeclarations() {
+            return this.localDeclarations;
+        }
+
+        /* (non-Javadoc)
+         * @see org.drools.rule.ReturnValueContextEntry#getWorkingMemory()
+         */
+        public InternalWorkingMemory getWorkingMemory() {
+            return this.workingMemory;
+        }
+        
+        public void resetTuple() {
+            this.leftTuple = null;
+        }
+        
+        public void resetFactHandle() {
+            this.handle = null;
+        }        
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Rule.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Rule.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/Rule.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,555 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.Calendar;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.drools.base.SalienceInteger;
+import org.drools.spi.AgendaGroup;
+import org.drools.spi.Consequence;
+import org.drools.spi.Duration;
+import org.drools.spi.Salience;
+
+/**
+ * A <code>Rule</code> contains a set of <code>Test</code>s and a
+ * <code>Consequence</code>.
+ * <p>
+ * The <code>Test</code>s describe the circumstances that representrepresent
+ * a match for this rule. The <code>Consequence</code> gets fired when the
+ * Conditions match.
+ *
+ * @author <a href="mailto:bob at eng.werken.com"> bob mcwhirter </a>
+ * @author <a href="mailto:simon at redhillconsulting.com.au"> Simon Harris </a>
+ * @author <a href="mailto:mproctor at codehaus.org"> mark proctor </a>
+ */
+public class Rule
+    implements
+    Serializable,
+    Dialectable {
+    /**
+     *
+     */
+    private static final long serialVersionUID = 400L;
+
+    /**   */
+    // ------------------------------------------------------------
+    // Instance members
+    // ------------------------------------------------------------
+    /** The parent pkg */
+    private String            pkg;
+
+    /** Name of the rule. */
+    private final String      name;
+
+    /** Salience value. */
+    private Salience               salience;
+
+    /** The Rule is dirty after patterns have been added */
+    private boolean           dirty;
+    private Map               declarations;
+    private Declaration[]     declarationArray;
+
+    private GroupElement      lhsRoot;
+
+    private String            dialect;
+
+    private String            agendaGroup;
+
+    /** Consequence. */
+    private Consequence       consequence;
+
+    /** Truthness duration. */
+    private Duration          duration;
+
+    /** Load order in Package */
+    private long              loadOrder;
+
+    /** Is recursion of this rule allowed */
+    private boolean           noLoop;
+
+    /** makes the rule's much the current focus */
+    private boolean           autoFocus;
+
+    private String            activationGroup;
+
+    private String            ruleFlowGroup;
+
+    private boolean           lockOnActive;
+
+    private boolean           hasLogicalDependency;
+
+    /** indicates that the rule is semantically correct. */
+    private boolean           semanticallyValid;
+
+    private Calendar          dateEffective;
+
+    private Calendar          dateExpires;
+
+    private boolean           enabled;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    /**
+     * Construct a
+     * <code>Rule<code> with the given name for the specified pkg parent
+     *
+     * @param name
+     *            The name of this rule.
+     */
+    public Rule(final String name,
+                final String pkg,
+                final String agendaGroup) {
+        this.name = name;
+        this.pkg = pkg;
+        this.agendaGroup = agendaGroup;
+        this.lhsRoot = GroupElementFactory.newAndInstance();
+        this.semanticallyValid = true;
+        this.enabled = true;
+        this.salience = SalienceInteger.DEFAULT_SALIENCE;
+    }
+
+    /**
+     * Construct a
+     * <code>Rule<code> with the given name for the specified pkg parent
+     *
+     * @param name
+     *            The name of this rule.
+     */
+    public Rule(final String name,
+                final String agendaGroup) {
+        this( name,
+              null,
+              agendaGroup );
+    }
+
+    public Rule(final String name) {
+        this( name,
+              null,
+              AgendaGroup.MAIN );
+    }
+
+
+
+    public String getDialect() {
+        return dialect;
+    }
+
+    public void setDialect(String dialect) {
+        this.dialect = dialect;
+    }
+
+    /**
+     * Set the truthness duration. This causes a delay before the firing of the
+     * <code>Consequence</code> if the rule is still true at the end of the
+     * duration.
+     *
+     * <p>
+     * This is merely a convenience method for calling
+     * {@link #setDuration(Duration)}with a <code>FixedDuration</code>.
+     * </p>
+     *
+     * @see #setDuration(Duration)
+     * @see FixedDuration
+     *
+     * @param seconds -
+     *            The number of seconds the rule must hold true in order to
+     *            fire.
+     */
+    public void setDuration(final long ms) {
+        this.duration = new FixedDuration( ms );
+    }
+
+    /**
+     * Set the truthness duration object. This causes a delay before the firing
+     * of the <code>Consequence</code> if the rule is still true at the end of
+     * the duration.
+     *
+     * @param duration
+     *            The truth duration object.
+     */
+    public void setDuration(final Duration duration) {
+        this.duration = duration;
+    }
+
+    /**
+     * Retrieve the truthness duration object.
+     *
+     * @return The truthness duration object.
+     */
+    public Duration getDuration() {
+        return this.duration;
+    }
+
+    /**
+     * Determine if this rule is internally consistent and valid.
+     * This will include checks to make sure the rules semantic components (actions and predicates)
+     * are valid.
+     *
+     * No exception is thrown.
+     * <p>
+     * A <code>Rule</code> must include at least one parameter declaration and
+     * one condition.
+     * </p>
+     *
+     * @return <code>true</code> if this rule is valid, else
+     *         <code>false</code>.
+     */
+    public boolean isValid() {
+        //if ( this.patterns.size() == 0 ) {
+        //    return false;
+        //}
+
+        if ( this.consequence == null || !isSemanticallyValid() ) {
+            return false;
+        }
+
+        return true;
+    }
+
+    public String getPackage() {
+        return this.pkg;
+    }
+
+    /**
+     * Retrieve the name of this rule.
+     *
+     * @return The name of this rule.
+     */
+    public String getName() {
+        return this.name;
+    }
+
+    /**
+     * Retrieve the <code>Rule</code> salience.
+     *
+     * @return The salience.
+     */
+    public Salience getSalience() {
+        return this.salience;
+    }
+
+    /**
+     * Set the <code>Rule<code> salience.
+     *
+     *  @param salience The salience.
+     */
+    public void setSalience(final Salience salience) {
+        this.salience = salience;
+    }
+
+    public String getAgendaGroup() {
+        return this.agendaGroup;
+    }
+
+    public void setAgendaGroup(final String agendaGroup) {
+        this.agendaGroup = agendaGroup;
+    }
+
+    public boolean isNoLoop() {
+        return this.noLoop;
+    }
+
+    /**
+     * This returns true is the rule is effective.
+     * If the rule is not effective, it cannot activate.
+     *
+     * This uses the dateEffective, dateExpires and enabled flag to decide this.
+     */
+    public boolean isEffective(TimeMachine tm) {
+        if ( !this.enabled ) {
+            return false;
+        }
+        if ( this.dateEffective == null && this.dateExpires == null ) {
+            return true;
+        } else {
+            final Calendar now = tm.getNow();
+
+            if ( this.dateEffective != null && this.dateExpires != null ) {
+                return (now.after( this.dateEffective ) && now.before( this.dateExpires ));
+            } else if ( this.dateEffective != null ) {
+                return (now.after( this.dateEffective ));
+            } else {
+                return (now.before( this.dateExpires ));
+            }
+
+        }
+    }
+
+    public void setNoLoop(final boolean noLoop) {
+        this.noLoop = noLoop;
+    }
+
+    public boolean getAutoFocus() {
+        return this.autoFocus;
+    }
+
+    public void setAutoFocus(final boolean autoFocus) {
+        this.autoFocus = autoFocus;
+    }
+
+    public String getActivationGroup() {
+        return this.activationGroup;
+    }
+
+    public void setActivationGroup(final String activationGroup) {
+        this.activationGroup = activationGroup;
+    }
+
+    public String getRuleFlowGroup() {
+        return this.ruleFlowGroup;
+    }
+
+    public void setRuleFlowGroup(final String ruleFlowGroup) {
+        this.ruleFlowGroup = ruleFlowGroup;
+    }
+
+    /**
+     * Retrieve a parameter <code>Declaration</code> by identifier.
+     *
+     * @param identifier
+     *            The identifier.
+     *
+     * @return The declaration or <code>null</code> if no declaration matches
+     *         the <code>identifier</code>.
+     */
+    public Declaration getDeclaration(final String identifier) {
+        if ( this.dirty || (this.declarations == null) ) {
+            this.declarations = this.lhsRoot.getOuterDeclarations();
+            this.declarationArray = (Declaration[]) this.declarations.values().toArray( new Declaration[this.declarations.values().size()] );
+            this.dirty = false;
+        }
+        return (Declaration) this.declarations.get( identifier );
+    }
+
+    /**
+     * This field is updated at runtime, when the first logical assertion is done. I'm currently not too happy about having this determine at runtime
+     * but its currently easier than trying to do this at compile time, although eventually this should be changed
+     * @return
+     */
+    public boolean hasLogicalDependency() {
+        return this.hasLogicalDependency;
+    }
+
+    public void setHasLogicalDependency(boolean hasLogicalDependency) {
+        this.hasLogicalDependency = hasLogicalDependency;
+    }
+
+    public boolean isLockOnActive() {
+        return this.lockOnActive;
+    }
+
+    public void setLockOnActive(final boolean lockOnActive) {
+        this.lockOnActive = lockOnActive;
+    }
+
+    /**
+     * Retrieve the set of all <i>root fact object </i> parameter
+     * <code>Declarations</code>.
+     *
+     * @return The Set of <code>Declarations</code> in order which specify the
+     *         <i>root fact objects</i>.
+     */
+    public Declaration[] getDeclarations() {
+        if ( this.dirty || (this.declarationArray == null) ) {
+            this.declarations = this.lhsRoot.getOuterDeclarations();
+            this.declarationArray = (Declaration[]) this.declarations.values().toArray( new Declaration[this.declarations.values().size()] );
+            this.dirty = false;
+        }
+        return this.declarationArray;
+    }
+
+    /**
+     * Add a pattern to the rule. All patterns are searched for bindings which are then added to the rule
+     * as declarations
+     *
+     * @param condition
+     *            The <code>Test</code> to add.
+     * @throws InvalidRuleException
+     */
+    public void addPattern(final RuleConditionElement element) {
+        this.dirty = true;
+        this.lhsRoot.addChild( element );
+    }
+
+    /**
+     * Retrieve the <code>List</code> of <code>Conditions</code> for this
+     * rule.
+     *
+     * @return The <code>List</code> of <code>Conditions</code>.
+     */
+    public GroupElement getLhs() {
+        return this.lhsRoot;
+    }
+
+    public void setLhs(final GroupElement lhsRoot) {
+        this.dirty = true;
+        this.lhsRoot = lhsRoot;
+    }
+
+    /**
+     * Uses the LogicTransformer to process the Rule patters - if no ORs are
+     * used this will return an array of a single AND element. If there are Ors
+     * it will return an And element for each possible logic branch. The
+     * processing uses as a clone of the Rule's patterns, so they are not
+     * changed.
+     *
+     * @return
+     * @throws InvalidPatternException
+     */
+    public GroupElement[] getTransformedLhs() throws InvalidPatternException {
+        return LogicTransformer.getInstance().transform( this.lhsRoot );
+    }
+
+    public int getSpecifity() {
+        return getSpecifity( this.lhsRoot );
+    }
+
+    private int getSpecifity(final GroupElement ce) {
+        int specificity = 0;
+        for ( final Iterator it = ce.getChildren().iterator(); it.hasNext(); ) {
+            final Object object = it.next();
+            if ( object instanceof Pattern ) {
+                specificity += getSpecifity( (Pattern) object );
+            } else if ( object instanceof GroupElement ) {
+                specificity += getSpecifity( (GroupElement) object );
+            }
+        }
+        return specificity;
+    }
+
+    private int getSpecifity(final Pattern pattern) {
+        int specificity = 0;
+        for ( final Iterator it = pattern.getConstraints().iterator(); it.hasNext(); ) {
+            if ( !(it.next() instanceof Declaration) ) {
+                specificity++;
+            }
+        }
+
+        return specificity;
+    }
+
+    /**
+     * Set the <code>Consequence</code> that is associated with the successful
+     * match of this rule.
+     *
+     * @param consequence
+     *            The <code>Consequence</code> to attach to this
+     *            <code>Rule</code>.
+     */
+    public void setConsequence(final Consequence consequence) {
+        this.consequence = consequence;
+    }
+
+    /**
+     * Retrieve the <code>Consequence</code> associated with this
+     * <code>Rule</code>.
+     *
+     * @return The <code>Consequence</code>.
+     */
+    public Consequence getConsequence() {
+        return this.consequence;
+    }
+
+    public long getLoadOrder() {
+        return this.loadOrder;
+    }
+
+    public void setLoadOrder(final long loadOrder) {
+        this.loadOrder = loadOrder;
+    }
+
+    public String toString() {
+        return "[Rule name=" + this.name + ", agendaGroup=" + this.agendaGroup + ", salience=" + this.salience + ", no-loop=" + this.noLoop + "]";
+    }
+
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + ((name == null) ? 0 : name.hashCode());
+        result = PRIME * result + ((pkg == null) ? 0 : pkg.hashCode());
+        return result;
+    }
+
+    public boolean equals(Object obj) {
+        if ( this == obj ) return true;
+        if ( !super.equals( obj ) ) return false;
+        if ( getClass() != obj.getClass() ) return false;
+        final Rule other = (Rule) obj;
+        if ( name == null ) {
+            if ( other.name != null ) return false;
+        } else if ( !name.equals( other.name ) ) return false;
+        if ( pkg == null ) {
+            if ( other.pkg != null ) return false;
+        } else if ( !pkg.equals( other.pkg ) ) return false;
+        return true;
+    }
+
+    public void setSemanticallyValid(final boolean valid) {
+        this.semanticallyValid = valid;
+    }
+
+    /**
+     * This will return if the semantic actions or predicates in the rules
+     * are valid.
+     * This is provided so that lists of rules can be provided even if their semantic actions
+     * do not "compile" etc.
+     */
+    public boolean isSemanticallyValid() {
+        return this.semanticallyValid;
+    }
+
+    /**
+     * Sets the date from which this rule takes effect (can include time to the millisecond).
+     * @param effectiveDate
+     */
+    public void setDateEffective(final Calendar effectiveDate) {
+        this.dateEffective = effectiveDate;
+    }
+
+    /**
+     * Sets the date after which the rule will no longer apply (can include time to the millisecond).
+     * @param expiresDate
+     */
+    public void setDateExpires(final Calendar expiresDate) {
+        this.dateExpires = expiresDate;
+    }
+
+
+    public Calendar getDateEffective() {
+        return this.dateEffective;
+    }
+
+    public Calendar getDateExpires() {
+        return this.dateExpires;
+    }
+
+    /**
+     * A rule is enabled by default. This can explicitly disable it in which case it will never activate.
+     */
+    public void setEnabled(final boolean b) {
+        this.enabled = b;
+    }
+
+    public boolean isEnabled() {
+        return this.enabled;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/RuleConditionElement.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/RuleConditionElement.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/RuleConditionElement.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2006 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.rule;
+
+import java.util.List;
+import java.util.Map;
+
+import org.drools.spi.RuleComponent;
+
+/**
+ * @author etirelli
+ *
+ */
+public interface RuleConditionElement
+    extends
+    RuleComponent,
+    Cloneable {
+
+    /**
+     * Returns a Map of declarations that are
+     * visible inside this conditional element
+     * 
+     * @return
+     */
+    public Map getInnerDeclarations();
+
+    /**
+     * Returns a Map of declarations that are visible
+     * outside this conditional element. 
+     * 
+     * @return
+     */
+    public Map getOuterDeclarations();
+
+    /**
+     * Resolves the given identifier in the current scope and
+     * returns the Declaration object for the declaration.
+     * Returns null if identifier can not be resolved.
+     *  
+     * @param identifier
+     * @return
+     */
+    public Declaration resolveDeclaration(String identifier);
+
+    /**
+     * Returns a clone from itself
+     * @return
+     */
+    public Object clone();
+    
+    /**
+     * Returs a list of RuleConditionElement's that are nested
+     * inside the current element
+     * @return
+     */
+    public List getNestedElements();
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/RuleConstructionException.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/RuleConstructionException.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/RuleConstructionException.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,62 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.RuntimeDroolsException;
+
+/**
+ * Base exception for errors during <code>Rule</code> construction.
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ */
+public class RuleConstructionException extends RuntimeDroolsException {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    /**
+     * @see java.lang.Exception#Exception()
+     */
+    RuleConstructionException() {
+        super();
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(String message)
+     */
+    RuleConstructionException(final String message) {
+        super( message );
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(String message, Throwable cause)
+     */
+    RuleConstructionException(final String message,
+                              final Throwable cause) {
+        super( message,
+               cause );
+    }
+
+    /**
+     * @see java.lang.Exception#Exception(Throwable cause)
+     */
+    RuleConstructionException(final Throwable cause) {
+        super( cause );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/TimeMachine.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/TimeMachine.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/TimeMachine.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,20 @@
+package org.drools.rule;
+
+import java.io.Serializable;
+import java.util.Calendar;
+
+/**
+ * This class allows the time for "now" to be defined outside of the Rule.
+ * Mainly for external testing tools (testing of rules, not drools).
+ *
+ * @author Michael Neale
+ */
+public class TimeMachine implements Serializable {
+
+    private static final long serialVersionUID = 400L;
+
+	public Calendar getNow() {
+		return Calendar.getInstance();
+	}
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/TimeWindow.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/TimeWindow.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/TimeWindow.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,51 @@
+package org.drools.rule;
+
+import org.drools.spi.Accumulator;
+
+public class TimeWindow extends Accumulate {
+
+	private long windowSize; 
+	
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 2009930636952909769L;
+
+	public TimeWindow(RuleConditionElement source, long windowSize) {
+		super(source);
+		// TODO Auto-generated constructor stub
+		this.windowSize = windowSize;
+	}
+
+	public TimeWindow(RuleConditionElement source,
+			Declaration[] requiredDeclarations, Declaration[] innerDeclarations, 
+			long windowSize) {
+		super(source, requiredDeclarations, innerDeclarations);
+		// TODO Auto-generated constructor stub
+		this.windowSize = windowSize;
+	}
+
+	public TimeWindow(RuleConditionElement source,
+			Declaration[] requiredDeclarations,
+			Declaration[] innerDeclarations, Accumulator accumulator,
+			long windowSize) {
+		super(source, requiredDeclarations, innerDeclarations, accumulator);
+		// TODO Auto-generated constructor stub
+		this.windowSize = windowSize;
+	}
+
+	/**
+	 * @return the windowSize
+	 */
+	public long getWindowSize() {
+		return windowSize;
+	}
+
+	/**
+	 * @param windowSize the windowSize to set
+	 */
+	public void setWindowSize(long windowSize) {
+		this.windowSize = windowSize;
+	}
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/TypeDeclaration.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/TypeDeclaration.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/TypeDeclaration.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2008 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.
+ *
+ * Created on Jan 23, 2008
+ */
+
+package org.drools.rule;
+
+import org.drools.facttemplates.FactTemplate;
+
+/**
+ * The type declaration class stores all type's metadata
+ * declared in source files.
+ *  
+ * @author etirelli
+ */
+public class TypeDeclaration {
+    
+    public static enum Role {
+        FACT,
+        EVENT;
+        
+        public static Role parseRole( String role ) {
+            if( "event".equalsIgnoreCase( role ) ) {
+                return EVENT;
+            } else if( "fact".equalsIgnoreCase( role ) ) {
+                return FACT;
+            }
+            return null;
+        }
+    }
+    
+    public static enum Format {
+        POJO, 
+        TEMPLATE;
+
+        public static Format parseFormat( String format ) {
+            if( "pojo".equalsIgnoreCase( format ) ) {
+                return POJO;
+            } else if( "template".equalsIgnoreCase( format ) ) {
+                return TEMPLATE;
+            }
+            return null;
+        }
+    }
+    
+    public static enum ClockStrategy {
+        NONE,
+        PSEUDO, 
+        SYSTEM, 
+        HEARTBEAT, 
+        ATTRIBUTE;
+        
+        public static ClockStrategy parseClockStrategy( String clockStrategy ) {
+            if( "none".equalsIgnoreCase( clockStrategy ) ) {
+                return NONE;
+            } else if( "pseudo".equalsIgnoreCase( clockStrategy ) ) {
+                return PSEUDO;
+            } else if( "system".equalsIgnoreCase( clockStrategy ) ) {
+                return SYSTEM;
+            } else if( "heartbeat".equalsIgnoreCase( clockStrategy ) ) {
+                return HEARTBEAT;
+            } else if( "attribute".equalsIgnoreCase( clockStrategy ) ) {
+                return ATTRIBUTE;
+            }
+            return null;
+        }
+    }
+
+    private final String typeName;
+    private Role role;
+    private Format format;
+    private ClockStrategy clockStrategy;
+    private String timestampAttribute;
+    private String durationAttribute;
+    private Class<?> typeClass;
+    private FactTemplate typeTemplate;
+    
+    public TypeDeclaration( String typeName ) {
+        this.typeName = typeName;
+        this.role = Role.FACT;
+        this.format = Format.POJO;
+        this.clockStrategy = ClockStrategy.NONE;
+        this.durationAttribute = null;
+        this.timestampAttribute = null;
+        this.typeClass = null;
+        this.typeTemplate = null;
+    }
+    
+    /**
+     * @return the type
+     */
+    public String getTypeName() {
+        return typeName;
+    }
+
+    /**
+     * @return the category
+     */
+    public Role getRole() {
+        return role;
+    }
+
+    /**
+     * @param role the category to set
+     */
+    public void setRole(Role role) {
+        this.role = role;
+    }
+
+    /**
+     * @return the format
+     */
+    public Format getFormat() {
+        return format;
+    }
+
+    /**
+     * @param format the format to set
+     */
+    public void setFormat(Format format) {
+        this.format = format;
+    }
+
+    /**
+     * @return the clockStrategy
+     */
+    public ClockStrategy getClockStrategy() {
+        return clockStrategy;
+    }
+
+    /**
+     * @param clockStrategy the clockStrategy to set
+     */
+    public void setClockStrategy(ClockStrategy clockStrategy) {
+        this.clockStrategy = clockStrategy;
+    }
+
+    /**
+     * @return the timestampAttribute
+     */
+    public String getTimestampAttribute() {
+        return timestampAttribute;
+    }
+
+    /**
+     * @param timestampAttribute the timestampAttribute to set
+     */
+    public void setTimestampAttribute(String timestampAttribute) {
+        this.timestampAttribute = timestampAttribute;
+    }
+
+    /**
+     * @return the durationAttribute
+     */
+    public String getDurationAttribute() {
+        return durationAttribute;
+    }
+
+    /**
+     * @param durationAttribute the durationAttribute to set
+     */
+    public void setDurationAttribute(String durationAttribute) {
+        this.durationAttribute = durationAttribute;
+    }
+
+    /**
+     * @return the typeClass
+     */
+    public Class< ? > getTypeClass() {
+        return typeClass;
+    }
+
+    /**
+     * @param typeClass the typeClass to set
+     */
+    public void setTypeClass(Class< ? > typeClass) {
+        this.typeClass = typeClass;
+    }
+
+    /**
+     * @return the typeTemplate
+     */
+    public FactTemplate getTypeTemplate() {
+        return typeTemplate;
+    }
+
+    /**
+     * @param typeTemplate the typeTemplate to set
+     */
+    public void setTypeTemplate(FactTemplate typeTemplate) {
+        this.typeTemplate = typeTemplate;
+    }
+    
+    /**
+     * Returns true if the given parameter matches this type declaration
+     * 
+     * @param clazz
+     * @return
+     */
+    public boolean matches( Object clazz ) {
+        boolean matches = false;
+        if( clazz instanceof FactTemplate ) {
+            matches = this.typeTemplate.equals( clazz );
+        } else {
+            matches = this.typeClass.isAssignableFrom( (Class<?>) clazz );
+        }
+        return matches;
+    }
+    
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/VariableConstraint.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/VariableConstraint.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/VariableConstraint.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,124 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldExtractor;
+
+public class VariableConstraint
+    implements
+    AlphaNodeFieldConstraint,
+    BetaNodeFieldConstraint {
+
+    private static final long         serialVersionUID = 400L;
+
+    private final FieldExtractor      fieldExtractor;
+    private final VariableRestriction restriction;
+
+    public VariableConstraint(final FieldExtractor fieldExtractor,
+                              final Declaration declaration,
+                              final Evaluator evaluator) {
+        this.fieldExtractor = fieldExtractor;
+        this.restriction = new VariableRestriction( fieldExtractor,
+                                                    declaration,
+                                                    evaluator );
+    }
+
+    public VariableConstraint(final FieldExtractor fieldExtractor,
+                              final VariableRestriction restriction) {
+        this.fieldExtractor = fieldExtractor;
+        this.restriction = restriction;
+    }
+
+    public Declaration[] getRequiredDeclarations() {
+        return this.restriction.getRequiredDeclarations();
+    }
+
+    public void replaceDeclaration(Declaration oldDecl,
+                                   Declaration newDecl) {
+        this.restriction.replaceDeclaration( oldDecl,
+                                             newDecl );
+    }
+
+    public FieldExtractor getFieldExtractor() {
+        return this.fieldExtractor;
+    }
+
+    public Evaluator getEvaluator() {
+        return this.restriction.getEvaluator();
+    }
+
+    public boolean isAllowed(final InternalFactHandle handle,
+                             final InternalWorkingMemory workingMemory) {
+        return this.restriction.isAllowed( this.fieldExtractor,
+                                           handle,
+                                           workingMemory );
+    }
+
+    public boolean isAllowedCachedLeft(final ContextEntry context,
+                                       final InternalFactHandle handle) {
+        return this.restriction.isAllowedCachedLeft( context,
+                                                     handle );
+    }
+
+    public boolean isAllowedCachedRight(final ReteTuple tuple,
+                                        final ContextEntry context) {
+        return this.restriction.isAllowedCachedRight( tuple,
+                                                      context );
+    }
+
+    public String toString() {
+        return "[VariableConstraint fieldExtractor=" + this.fieldExtractor + " declaration=" + getRequiredDeclarations() + "]";
+    }
+
+    public ContextEntry getContextEntry() {
+        return this.restriction.getContextEntry();
+    }
+
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + this.fieldExtractor.hashCode();
+        result = PRIME * result + this.restriction.hashCode();
+        return result;
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || getClass() != object.getClass() ) {
+            return false;
+        }
+
+        final VariableConstraint other = (VariableConstraint) object;
+
+        return this.fieldExtractor.equals( other.fieldExtractor ) && this.restriction.equals( other.restriction );
+    }
+
+    public Object clone() {
+        return new VariableConstraint( this.fieldExtractor,
+                                       (VariableRestriction) this.restriction.clone() );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/VariableRestriction.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/VariableRestriction.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/rule/VariableRestriction.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,452 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Arrays;
+
+import org.drools.base.ValueType;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.Restriction;
+
+public class VariableRestriction
+    implements
+    Restriction {
+
+    private static final long          serialVersionUID = 400L;
+
+    private Declaration                declaration;
+
+    private final Declaration[]        requiredDeclarations;
+
+    private final Evaluator            evaluator;
+
+    private final VariableContextEntry contextEntry;
+
+    public VariableRestriction(final FieldExtractor fieldExtractor,
+                               final Declaration declaration,
+                               final Evaluator evaluator) {
+        this.declaration = declaration;
+        this.requiredDeclarations = new Declaration[]{declaration};
+        this.evaluator = evaluator;
+        this.contextEntry = this.createContextEntry( this.evaluator,
+                                                     fieldExtractor );
+    }
+
+    public Declaration[] getRequiredDeclarations() {
+        return this.requiredDeclarations;
+    }
+
+    public void replaceDeclaration(Declaration oldDecl,
+                                   Declaration newDecl) {
+        if ( this.declaration.equals( oldDecl ) ) {
+            this.declaration = newDecl;
+            this.requiredDeclarations[0] = newDecl;
+            this.contextEntry.declaration = newDecl;
+        }
+    }
+
+    public Evaluator getEvaluator() {
+        return this.evaluator;
+    }
+
+    public boolean isAllowed(final Extractor extractor,
+                             final InternalFactHandle handle,
+                             final InternalWorkingMemory workingMemory) {
+        return this.evaluator.evaluate( workingMemory,
+                                        this.contextEntry.extractor,
+                                        this.evaluator.prepareObject( handle ),
+                                        this.contextEntry.declaration.getExtractor(),
+                                        this.evaluator.prepareObject( handle ) );
+    }
+
+    public boolean isAllowedCachedLeft(final ContextEntry context,
+                                       final InternalFactHandle handle) {
+        return this.evaluator.evaluateCachedLeft( ((VariableContextEntry) context).workingMemory,
+                                                  (VariableContextEntry) context,
+                                                  this.evaluator.prepareObject( handle ) );
+    }
+
+    public boolean isAllowedCachedRight(final ReteTuple tuple,
+                                        final ContextEntry context) {
+        return this.evaluator.evaluateCachedRight( ((VariableContextEntry) context).workingMemory,
+                                                   (VariableContextEntry) context,
+                                                   this.evaluator.prepareObject( tuple.get( this.declaration ) ) );
+    }
+
+    public String toString() {
+        return "[VariableRestriction declaration=" + this.declaration + "]";
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#hashCode()
+     */
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + ((this.declaration == null) ? 0 : this.declaration.hashCode());
+        result = PRIME * result + ((this.evaluator == null) ? 0 : this.evaluator.hashCode());
+        result = PRIME * result + this.requiredDeclarations[0].hashCode();
+        return result;
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || getClass() != object.getClass() ) {
+            return false;
+        }
+
+        final VariableRestriction other = (VariableRestriction) object;
+
+        return this.declaration.equals( other.declaration ) && this.evaluator.equals( other.evaluator ) && Arrays.equals( this.requiredDeclarations,
+                                                                                                                          other.requiredDeclarations );
+    }
+
+    private final VariableContextEntry createContextEntry(final Evaluator eval,
+                                                          final FieldExtractor fieldExtractor) {
+        ValueType coerced = eval.getCoercedValueType();
+        
+        if ( coerced.isBoolean() ) {
+            return new BooleanVariableContextEntry( fieldExtractor,
+                                                    this.declaration,
+                                                    this.evaluator );
+        } else if ( coerced.isFloatNumber() ) {
+            return new DoubleVariableContextEntry( fieldExtractor,
+                                                   this.declaration,
+                                                   this.evaluator );
+        } else if ( coerced.isIntegerNumber() ) {
+            return new LongVariableContextEntry( fieldExtractor,
+                                                 this.declaration,
+                                                 this.evaluator );
+        } else if ( coerced.isChar() ) {
+            return new CharVariableContextEntry( fieldExtractor,
+                                                 this.declaration,
+                                                 this.evaluator );
+        } else {
+            return new ObjectVariableContextEntry( fieldExtractor,
+                                                   this.declaration,
+                                                   this.evaluator );
+        }
+    }
+
+    public ContextEntry getContextEntry() {
+        return this.contextEntry;
+    }
+
+    public Object clone() {
+        return new VariableRestriction( this.contextEntry.extractor,
+                                        (Declaration) this.declaration.clone(),
+                                        this.evaluator );
+    }
+
+    public static abstract class VariableContextEntry
+        implements
+        ContextEntry {
+        public FieldExtractor        extractor;
+        public Evaluator             evaluator;
+        public Object                object;
+        public Declaration           declaration;
+        public ReteTuple             reteTuple;
+        public ContextEntry          entry;
+        public boolean               leftNull;
+        public boolean               rightNull;
+        public InternalWorkingMemory workingMemory;
+
+        public VariableContextEntry(final FieldExtractor extractor,
+                                    final Declaration declaration,
+                                    final Evaluator evaluator) {
+            this.extractor = extractor;
+            this.declaration = declaration;
+            this.evaluator = evaluator;
+        }
+
+        public ContextEntry getNext() {
+            return this.entry;
+        }
+
+        public void setNext(final ContextEntry entry) {
+            this.entry = entry;
+        }
+
+        public FieldExtractor getFieldExtractor() {
+            return this.extractor;
+        }
+
+        public Object getObject() {
+            return this.object;
+        }
+
+        public ReteTuple getTuple() {
+            return this.reteTuple;
+        }
+
+        public Declaration getVariableDeclaration() {
+            return this.declaration;
+        }
+
+        public boolean isLeftNull() {
+            return this.leftNull;
+        }
+
+        public boolean isRightNull() {
+            return this.rightNull;
+        }
+        
+        public void resetTuple() {
+            this.reteTuple = null;
+        }
+        
+        public void resetFactHandle() {
+            this.object = null;
+        }        
+    }
+
+    public static class ObjectVariableContextEntry extends VariableContextEntry {
+
+        private static final long serialVersionUID = 400L;
+        public Object             left;
+        public Object             right;
+
+        public ObjectVariableContextEntry(final FieldExtractor extractor,
+                                          final Declaration declaration,
+                                          final Evaluator evaluator) {
+            super( extractor,
+                   declaration,
+                   evaluator);
+        }
+
+        public void updateFromTuple(final InternalWorkingMemory workingMemory,
+                                    final ReteTuple tuple) {
+            this.reteTuple = tuple;
+            this.workingMemory = workingMemory;
+            this.leftNull = this.declaration.getExtractor().isNullValue( workingMemory,
+                                                                         evaluator.prepareObject( tuple.get( this.declaration ) ) );
+            this.left = this.declaration.getExtractor().getValue( workingMemory,
+                                                                  evaluator.prepareObject( tuple.get( this.declaration ) ) );
+        }
+
+        public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
+                                         final InternalFactHandle handle) {
+            this.object = evaluator.prepareObject( handle );
+            this.workingMemory = workingMemory;
+            this.rightNull = this.extractor.isNullValue( workingMemory,
+                                                         evaluator.prepareObject( handle ) );
+            this.right = this.extractor.getValue( workingMemory,
+                                                  evaluator.prepareObject( handle ) );
+        }
+        
+        public void resetTuple() {
+            this.left = null;
+            this.reteTuple = null;
+        }
+        
+        public void resetFactHandle() {
+            this.right = null;
+            this.object = null;
+        }        
+    }
+
+    public static class LongVariableContextEntry extends VariableContextEntry {
+
+        private static final long serialVersionUID = 400L;
+
+        public long               left;
+        public long               right;
+
+        public LongVariableContextEntry(final FieldExtractor extractor,
+                                        final Declaration declaration,
+                                        final Evaluator evaluator) {
+            super( extractor,
+                   declaration,
+                   evaluator );
+        }
+
+        public void updateFromTuple(final InternalWorkingMemory workingMemory,
+                                    final ReteTuple tuple) {
+            this.reteTuple = tuple;
+            this.workingMemory = workingMemory;
+            this.leftNull = this.declaration.getExtractor().isNullValue( workingMemory,
+                                                                         evaluator.prepareObject( tuple.get( this.declaration ) ) );
+
+            if ( !leftNull ) {
+                this.left = this.declaration.getExtractor().getLongValue( workingMemory,
+                                                                          evaluator.prepareObject( tuple.get( this.declaration ) ) );
+            } else {
+                this.left = 0;
+            }
+        }
+
+        public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
+                                         final InternalFactHandle handle) {
+            this.object = evaluator.prepareObject( handle );
+            this.workingMemory = workingMemory;
+            this.rightNull = this.extractor.isNullValue( workingMemory,
+                                                         evaluator.prepareObject( handle ) );
+
+            if ( !rightNull ) { // avoid a NullPointerException
+                this.right = this.extractor.getLongValue( workingMemory,
+                                                          evaluator.prepareObject( handle ) );
+            } else {
+                this.right = 0;
+            }
+        }
+    }
+
+    public static class CharVariableContextEntry extends VariableContextEntry {
+
+        private static final long serialVersionUID = 400L;
+
+        public char               left;
+        public char               right;
+
+        public CharVariableContextEntry(final FieldExtractor extractor,
+                                        final Declaration declaration,
+                                        final Evaluator evaluator) {
+            super( extractor,
+                   declaration,
+                   evaluator );
+        }
+
+        public void updateFromTuple(final InternalWorkingMemory workingMemory,
+                                    final ReteTuple tuple) {
+            this.reteTuple = tuple;
+            this.workingMemory = workingMemory;
+            this.leftNull = this.declaration.getExtractor().isNullValue( workingMemory,
+                                                                         evaluator.prepareObject( tuple.get( this.declaration ) ) );
+
+            if ( !leftNull ) {
+                this.left = this.declaration.getExtractor().getCharValue( workingMemory,
+                                                                          evaluator.prepareObject( tuple.get( this.declaration ) ) );
+            } else {
+                this.left = 0;
+            }
+        }
+
+        public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
+                                         final InternalFactHandle handle) {
+            this.object = evaluator.prepareObject( handle );
+            this.workingMemory = workingMemory;
+            this.rightNull = this.extractor.isNullValue( workingMemory,
+                                                         evaluator.prepareObject( handle ) );
+
+            if ( !rightNull ) { // avoid a NullPointerException
+                this.right = this.extractor.getCharValue( workingMemory,
+                                                          evaluator.prepareObject( handle ) );
+            } else {
+                this.right = 0;
+            }
+        }
+    }
+
+    public static class DoubleVariableContextEntry extends VariableContextEntry {
+
+        private static final long serialVersionUID = 400L;
+
+        public double             left;
+        public double             right;
+
+        public DoubleVariableContextEntry(final FieldExtractor extractor,
+                                          final Declaration declaration,
+                                          final Evaluator evaluator) {
+            super( extractor,
+                   declaration,
+                   evaluator );
+        }
+
+        public void updateFromTuple(final InternalWorkingMemory workingMemory,
+                                    final ReteTuple tuple) {
+            this.reteTuple = tuple;
+            this.workingMemory = workingMemory;
+            this.leftNull = this.declaration.getExtractor().isNullValue( workingMemory,
+                                                                         evaluator.prepareObject( tuple.get( this.declaration ) ) );
+
+            if ( !leftNull ) {
+                this.left = this.declaration.getExtractor().getDoubleValue( workingMemory,
+                                                                            evaluator.prepareObject( tuple.get( this.declaration ) ) );
+            } else {
+                this.left = 0;
+            }
+        }
+
+        public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
+                                         final InternalFactHandle handle) {
+            this.object = evaluator.prepareObject( handle );
+            this.workingMemory = workingMemory;
+            this.rightNull = this.extractor.isNullValue( workingMemory,
+                                                         evaluator.prepareObject( handle ) );
+
+            if ( !rightNull ) { // avoid a NullPointerException
+                this.right = this.extractor.getDoubleValue( workingMemory,
+                                                            evaluator.prepareObject( handle ) );
+            } else {
+                this.right = 0;
+            }
+        }
+    }
+
+    public static class BooleanVariableContextEntry extends VariableContextEntry {
+
+        private static final long serialVersionUID = 400L;
+        public boolean            left;
+        public boolean            right;
+
+        public BooleanVariableContextEntry(final FieldExtractor extractor,
+                                           final Declaration declaration,
+                                           final Evaluator evaluator) {
+            super( extractor,
+                   declaration,
+                   evaluator );
+        }
+
+        public void updateFromTuple(final InternalWorkingMemory workingMemory,
+                                    final ReteTuple tuple) {
+            this.reteTuple = tuple;
+            this.workingMemory = workingMemory;
+            this.leftNull = this.declaration.getExtractor().isNullValue( workingMemory,
+                                                                         evaluator.prepareObject( tuple.get( this.declaration ) ) );
+
+            if ( !leftNull ) {
+                this.left = this.declaration.getExtractor().getBooleanValue( workingMemory,
+                                                                             evaluator.prepareObject( tuple.get( this.declaration ) ) );
+            } else {
+                this.left = false;
+            }
+        }
+
+        public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
+                                         final InternalFactHandle handle) {
+            this.object = evaluator.prepareObject( handle );
+            this.workingMemory = workingMemory;
+            this.rightNull = this.extractor.isNullValue( workingMemory,
+                                                         evaluator.prepareObject( handle ) );
+
+            if ( !rightNull ) { // avoid a NullPointerException
+                this.right = this.extractor.getBooleanValue( workingMemory,
+                                                             evaluator.prepareObject( handle ) );
+            } else {
+                this.right = false;
+            }
+        }
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/core/RuleFlowProcess.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/core/RuleFlowProcess.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/core/RuleFlowProcess.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,47 @@
+package org.drools.ruleflow.core;
+
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.NodeContainer;
+import org.drools.workflow.core.impl.NodeContainerImpl;
+import org.drools.workflow.core.impl.WorkflowProcessImpl;
+import org.drools.workflow.core.node.StartNode;
+
+public class RuleFlowProcess extends WorkflowProcessImpl {
+
+    public static final String RULEFLOW_TYPE = "RuleFlow";
+
+    private static final long serialVersionUID = 400L;
+    
+    public RuleFlowProcess() {
+        setType(RULEFLOW_TYPE);
+    }
+
+    protected NodeContainer createNodeContainer() {
+        return new WorkflowProcessNodeContainer();
+    }
+    
+    public StartNode getStart() {
+        Node[] nodes = getNodes();
+        for (int i = 0; i < nodes.length; i++) {
+            if (nodes[i] instanceof StartNode) {
+                return (StartNode) nodes[i];
+            }
+        }
+        return null;
+    }
+
+    private class WorkflowProcessNodeContainer extends NodeContainerImpl {
+        
+        private static final long serialVersionUID = 400L;
+
+        protected void validateAddNode(Node node) {
+            super.validateAddNode(node);
+            if ((node instanceof StartNode) && (getStart() != null)) {
+                throw new IllegalArgumentException(
+                    "A RuleFlowProcess cannot have more than one start node!");
+            }
+        }
+        
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/core/validation/RuleFlowProcessValidator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/core/validation/RuleFlowProcessValidator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/core/validation/RuleFlowProcessValidator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,323 @@
+package org.drools.ruleflow.core.validation;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.process.core.Process;
+import org.drools.process.core.Variable;
+import org.drools.process.core.Work;
+import org.drools.process.core.validation.ProcessValidationError;
+import org.drools.process.core.validation.ProcessValidator;
+import org.drools.process.core.validation.impl.ProcessValidationErrorImpl;
+import org.drools.ruleflow.core.RuleFlowProcess;
+import org.drools.workflow.core.Connection;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.impl.DroolsConsequenceAction;
+import org.drools.workflow.core.node.ActionNode;
+import org.drools.workflow.core.node.EndNode;
+import org.drools.workflow.core.node.Join;
+import org.drools.workflow.core.node.MilestoneNode;
+import org.drools.workflow.core.node.RuleSetNode;
+import org.drools.workflow.core.node.Split;
+import org.drools.workflow.core.node.StartNode;
+import org.drools.workflow.core.node.SubProcessNode;
+import org.drools.workflow.core.node.WorkItemNode;
+import org.mvel.ErrorDetail;
+import org.mvel.ExpressionCompiler;
+import org.mvel.ParserContext;
+
+/**
+ * Default implementation of a RuleFlow validator.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class RuleFlowProcessValidator implements ProcessValidator {
+    
+    // TODO: make this pluggable
+    // TODO: extract generic process stuff and generic workflow stuff
+
+    private static RuleFlowProcessValidator instance;
+
+    private RuleFlowProcessValidator() {
+    }
+
+    public static RuleFlowProcessValidator getInstance() {
+        if ( instance == null ) {
+            instance = new RuleFlowProcessValidator();
+        }
+        return instance;
+    }
+
+    public ProcessValidationError[] validateProcess(final RuleFlowProcess process) {
+        final List<ProcessValidationError> errors = new ArrayList<ProcessValidationError>();
+
+        if (process.getName() == null) {
+            errors.add(new ProcessValidationErrorImpl(process,
+                "Process has no name."));
+        }
+
+        if (process.getId() == null || "".equals(process.getId())) {
+            errors.add(new ProcessValidationErrorImpl(process,
+                "Process has no id."));
+        }
+
+        if ( process.getPackageName() == null || "".equals( process.getPackageName() ) ) {
+            errors.add(new ProcessValidationErrorImpl(process,
+                "Process has no package name."));
+        }
+
+        // check start node of process
+        if ( process.getStart() == null ) {
+            errors.add(new ProcessValidationErrorImpl(process,
+                "Process has no start node."));
+        }
+
+        boolean startNodeFound = false;
+        boolean endNodeFound = false;
+        final Node[] nodes = process.getNodes();
+        for ( int i = 0; i < nodes.length; i++ ) {
+            final Node node = nodes[i];
+            if (node instanceof StartNode) {
+                final StartNode startNode = (StartNode) node;
+                startNodeFound = true;
+                if (startNode.getTo() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Start node '" + node.getName() + "' [" + node.getId() + "] has no outgoing connection."));
+                }
+            } else if (node instanceof EndNode) {
+                final EndNode endNode = (EndNode) node;
+                endNodeFound = true;
+                if (endNode.getFrom() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "End node '" + node.getName() + "' [" + node.getId() + "] has no incoming connection."));
+                }
+            } else if (node instanceof RuleSetNode) {
+                final RuleSetNode ruleSetNode = (RuleSetNode) node;
+                if (ruleSetNode.getFrom() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "RuleSet node '" + node.getName() + "' [" + node.getId() + "] has no incoming connection."));
+                }
+                if (ruleSetNode.getTo() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "RuleSet node '" + node.getName() + "' [" + node.getId() + "] has no outgoing connection."));
+                }
+                final String ruleFlowGroup = ruleSetNode.getRuleFlowGroup();
+                if (ruleFlowGroup == null || "".equals(ruleFlowGroup)) {
+                    errors.add( new ProcessValidationErrorImpl(process,
+                        "RuleSet node '" + node.getName() + "' [" + node.getId() + "] has no ruleflow-group."));
+                }
+            } else if (node instanceof Split) {
+                final Split split = (Split) node;
+                if (split.getType() == Split.TYPE_UNDEFINED) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Split node '" + node.getName() + "' [" + node.getId() + "] has no type."));
+                }
+                if (split.getFrom() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Split node '" + node.getName() + "' [" + node.getId() + "] has no incoming connection."));
+                }
+                if (split.getDefaultOutgoingConnections().size() < 2) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Split node '" + node.getName() + "' [" + node.getId() + "] does not have more than one outgoing connection: " + split.getOutgoingConnections().size() + "."));
+                }
+                if (split.getType() == Split.TYPE_XOR || split.getType() == Split.TYPE_OR ) {
+                    for ( final Iterator<Connection> it = split.getDefaultOutgoingConnections().iterator(); it.hasNext(); ) {
+                        final Connection connection = it.next();
+                        if (split.getConstraint(connection) == null) {
+                            errors.add(new ProcessValidationErrorImpl(process,
+                                "Split node '" + node.getName() + "' [" + node.getId() + "] does not have a constraint for " + connection.toString() + "."));
+                        }
+                    }
+                }
+            } else if ( node instanceof Join ) {
+                final Join join = (Join) node;
+                if (join.getType() == Join.TYPE_UNDEFINED) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Join node '" + node.getName() + "' [" + node.getId() + "] has no type."));
+                }
+                if (join.getDefaultIncomingConnections().size() < 2) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Join node '" + node.getName() + "' [" + node.getId() + "] does not have more than one incoming connection: " + join.getIncomingConnections().size() + "."));
+                }
+                if (join.getTo() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Join node '" + node.getName() + "' [" + node.getId() + "] has no outgoing connection."));
+                }
+            } else if (node instanceof MilestoneNode) {
+                final MilestoneNode milestone = (MilestoneNode) node;
+                if (milestone.getFrom() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Milestone node '" + node.getName() + "' [" + node.getId() + "] has no incoming connection."));
+                }
+
+                if (milestone.getTo() == null) {
+                    errors.add( new ProcessValidationErrorImpl(process,
+                        "Milestone node '" + node.getName() + "' [" + node.getId() + "] has no outgoing connection."));
+                }
+                if (milestone.getConstraint() == null) {
+                    errors.add( new ProcessValidationErrorImpl(process,
+                        "Milestone node '" + node.getName() + "' [" + node.getId() + "] has no constraint."));
+                }
+            } else if (node instanceof SubProcessNode) {
+                final SubProcessNode subProcess = (SubProcessNode) node;
+                if (subProcess.getFrom() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "SubProcess node '" + node.getName() + "' [" + node.getId() + "] has no incoming connection."));
+                }
+                if (subProcess.getTo() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "SubProcess node '" + node.getName() + "' [" + node.getId() + "] has no outgoing connection."));
+                }
+                if (subProcess.getProcessId() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "SubProcess node '" + node.getName() + "' [" + node.getId() + "] has no process id."));
+                }
+            } else if (node instanceof ActionNode) {
+                final ActionNode actionNode = (ActionNode) node;
+                if (actionNode.getFrom() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Action node '" + node.getName() + "' [" + node.getId() + "] has no incoming connection."));
+                }
+                if (actionNode.getTo() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Action node '" + node.getName() + "' [" + node.getId() + "] has no outgoing connection."));
+                }
+                if (actionNode.getAction() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "Action node '" + node.getName() + "' [" + node.getId() + "] has no action."));
+                } else {
+                	if (actionNode.getAction() instanceof DroolsConsequenceAction) {
+                		DroolsConsequenceAction droolsAction = (DroolsConsequenceAction) actionNode.getAction();
+                		String actionString = droolsAction.getConsequence();
+                		if (actionString == null) {
+                            errors.add(new ProcessValidationErrorImpl(process,
+                                "Action node '" + node.getName() + "' [" + node.getId() + "] has empty action."));
+                		} else {
+	                    	try {
+	                    		ExpressionCompiler compiler = new ExpressionCompiler(actionString);
+	                    		compiler.setVerifying(true);
+		                		ParserContext parserContext = new ParserContext();
+		                		//parserContext.setStrictTypeEnforcement(true);
+		                		compiler.compile(parserContext);
+		                		List<ErrorDetail> mvelErrors = parserContext.getErrorList();
+		                		if (mvelErrors != null) {
+		                			for (Iterator<ErrorDetail> iterator = mvelErrors.iterator(); iterator.hasNext(); ) {
+		                			    ErrorDetail error = iterator.next();
+		                                errors.add(new ProcessValidationErrorImpl(process,
+	                                        "Action node '" + node.getName() + "' [" + node.getId() + "] has invalid action: " + error.getMessage() + "."));
+		                			}
+		                		}
+	                    	} catch (Throwable t) {
+                                errors.add(new ProcessValidationErrorImpl(process,
+                                    "Action node '" + node.getName() + "' [" + node.getId() + "] has invalid action: " + t.getMessage() + "."));
+	                    	}
+                		}
+                	}
+                }
+            } else if (node instanceof WorkItemNode) {
+                final WorkItemNode workItemNode = (WorkItemNode) node;
+                if (workItemNode.getFrom() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "WorkItem node '" + node.getName() + "' [" + node.getId() + "] has no incoming connection."));
+                }
+                if (workItemNode.getTo() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "WorkItem node '" + node.getName() + "' [" + node.getId() + "] has no outgoing connection."));
+                }
+                if (workItemNode.getWork() == null) {
+                    errors.add(new ProcessValidationErrorImpl(process,
+                        "WorkItem node '" + node.getName() + "' [" + node.getId() + "] has no work specified."));
+                } else {
+                    Work work = workItemNode.getWork();
+                    if (work.getName() == null) {
+                        errors.add(new ProcessValidationErrorImpl(process,
+                            "WorkItem node '" + node.getName() + "' [" + node.getId() + "] has no work name."));
+                    }
+                }
+            } 
+        }
+        if (!startNodeFound) {
+            errors.add(new ProcessValidationErrorImpl(process,
+                "Process has no start node."));
+        }
+        if (!endNodeFound) {
+            errors.add(new ProcessValidationErrorImpl(process,
+                "Process has no end node."));
+        }
+        for (final Iterator<Variable> it = process.getVariables().iterator(); it.hasNext(); ) {
+            final Variable variable = it.next();
+            if (variable.getType() == null) {
+                errors.add(new ProcessValidationErrorImpl(process,
+                    "Variable '" + variable.getName() + "' has no type."));
+            }
+        }
+
+        checkAllNodesConnectedToStart(process, errors);
+
+        return errors.toArray(new ProcessValidationError[errors.size()]);
+    }
+
+    private void checkAllNodesConnectedToStart(final RuleFlowProcess process,
+                                               final List<ProcessValidationError> errors) {
+        final Map<Node, Boolean> processNodes = new HashMap<Node, Boolean>();
+        final Node[] nodes = process.getNodes();
+        for (int i = 0; i < nodes.length; i++) {
+            final Node node = nodes[i];
+            processNodes.put(node, Boolean.FALSE);
+        }
+        final Node start = process.getStart();
+        if (start != null) {
+            processNode(start, processNodes);
+        }
+        for ( final Iterator<Node> it = processNodes.keySet().iterator(); it.hasNext(); ) {
+            final Node node = it.next();
+            if (Boolean.FALSE.equals(processNodes.get(node))) {
+                errors.add(new ProcessValidationErrorImpl(process,
+                    "Node '" + node.getName() + "' [" + node.getId() + "] has no connection to the start node."));
+            }
+        }
+    }
+
+    private void processNode(final Node node, final Map<Node, Boolean> nodes) {
+        if (!nodes.containsKey(node) ) {
+            throw new IllegalStateException("A process node is connected with a node that does not belong to the process.");
+        }
+        final Boolean prevValue = (Boolean) nodes.put(node, Boolean.TRUE);
+        if (prevValue == Boolean.FALSE) {
+            for (final Iterator<List<Connection>> it = node.getOutgoingConnections().values().iterator(); it.hasNext(); ) {
+                final List<Connection> list = it.next();
+                for (final Iterator<Connection> it2 = list.iterator(); it2.hasNext(); ) {
+                    processNode(it2.next().getTo(), nodes);
+                }
+            }
+        }
+    }
+
+    public ProcessValidationError[] validateProcess(Process process) {
+        if (!(process instanceof RuleFlowProcess)) {
+            throw new IllegalArgumentException(
+                "This validator can only validate ruleflow processes!");
+        }
+        return validateProcess((RuleFlowProcess) process);
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/instance/RuleFlowProcessInstance.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/instance/RuleFlowProcessInstance.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/instance/RuleFlowProcessInstance.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,18 @@
+package org.drools.ruleflow.instance;
+
+import org.drools.ruleflow.core.RuleFlowProcess;
+import org.drools.workflow.instance.impl.WorkflowProcessInstanceImpl;
+
+public class RuleFlowProcessInstance extends WorkflowProcessInstanceImpl {
+
+    private static final long serialVersionUID = 400L;
+    
+    public RuleFlowProcess getRuleFlowProcess() {
+        return (RuleFlowProcess) getProcess();
+    }
+
+    public void internalStart() {
+        getNodeInstance( getRuleFlowProcess().getStart() ).trigger( null, null );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/instance/RuleFlowProcessInstanceFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/instance/RuleFlowProcessInstanceFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/ruleflow/instance/RuleFlowProcessInstanceFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,18 @@
+package org.drools.ruleflow.instance;
+
+import java.io.Serializable;
+
+import org.drools.process.instance.ProcessInstance;
+import org.drools.process.instance.ProcessInstanceFactory;
+
+public class RuleFlowProcessInstanceFactory implements ProcessInstanceFactory, Serializable {
+
+    private static final long serialVersionUID = 400L;
+
+    public ProcessInstance createProcessInstance() {
+        return new RuleFlowProcessInstance();
+    }
+    
+    
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Accumulator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Accumulator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Accumulator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.spi;
+
+import org.drools.WorkingMemory;
+import org.drools.common.InternalFactHandle;
+import org.drools.rule.Declaration;
+
+/**
+ * Accumulator
+ *
+ * Created: 04/06/2006
+ * @author <a href="mailto:tirelli at post.com">Edson Tirelli</a> 
+ *
+ * @version $Id: Accumulator.java 13464 2007-07-13 22:15:50Z tirelli $
+ */
+public interface Accumulator
+    extends
+    Invoker {
+    
+    /**
+     * Creates and return a context object for each working memory instance
+     * 
+     * @return
+     */
+    public Object createWorkingMemoryContext();
+    
+    /**
+     * Creates the context object for an accumulator session.
+     * The context is passed as a parameter to every subsequent accumulator
+     * method call in the same session.
+     * 
+     * @return
+     */
+    public Object createContext();
+
+    /**
+     * Executes the initialization block of code
+     * 
+     * @param leftTuple tuple causing the rule fire
+     * @param declarations previous declarations
+     * @param workingMemory
+     * @throws Exception
+     */
+    public void init(Object workingMemoryContext,
+                     Object context,
+                     Tuple leftTuple,
+                     Declaration[] declarations,
+                     WorkingMemory workingMemory) throws Exception;
+
+    /**
+     * Executes the accumulate (action) code for the given fact handle
+     * 
+     * @param leftTuple
+     * @param handle
+     * @param declarations
+     * @param innerDeclarations
+     * @param workingMemory
+     * @throws Exception
+     */
+    public void accumulate(Object workingMemoryContext,
+                           Object context,
+                           Tuple leftTuple,
+                           InternalFactHandle handle,
+                           Declaration[] declarations,
+                           Declaration[] innerDeclarations,
+                           WorkingMemory workingMemory) throws Exception;
+    
+    /**
+     * Returns true if this accumulator supports operation reversal
+     * 
+     * @return
+     */
+    public boolean supportsReverse();
+    
+    /**
+     * Reverses the accumulate action for the given fact handle
+     * 
+     * @param context
+     * @param leftTuple
+     * @param handle
+     * @param declarations
+     * @param innerDeclarations
+     * @param workingMemory
+     * @throws Exception
+     */
+    public void reverse(Object workingMemoryContext,
+                        Object context,
+                        Tuple leftTuple,
+                        InternalFactHandle handle,
+                        Declaration[] declarations,
+                        Declaration[] innerDeclarations,
+                        WorkingMemory workingMemory) throws Exception;
+
+    /**
+     * Gets the result of the accummulation
+     * 
+     * @param leftTuple
+     * @param declarations
+     * @param workingMemory
+     * @return
+     * @throws Exception
+     */
+    public Object getResult(Object workingMemoryContext,
+                            Object context, 
+                            Tuple leftTuple,
+                            Declaration[] declarations,
+                            WorkingMemory workingMemory) throws Exception;
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Action.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Action.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Action.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,8 @@
+package org.drools.spi;
+
+import org.drools.WorkingMemory;
+import org.drools.rule.Dialectable;
+
+public interface Action {
+    void execute(WorkingMemory workingMemory) throws Exception ;
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Activation.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Activation.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Activation.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,102 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.drools.common.ActivationGroupNode;
+import org.drools.common.LogicalDependency;
+import org.drools.common.RuleFlowGroupNode;
+import org.drools.rule.GroupElement;
+import org.drools.rule.Rule;
+import org.drools.util.LinkedList;
+
+/**
+ * When a <code>Tuple</code> fully matches a rule it is added to the <code>Agenda</code>
+ * As an <code>Activation</code>. Each <code>Activation</code> is assigned a number, this 
+ * number is determined by the <code>WorkingMemory</code> all <code>Activations</code> created 
+ * from a single insert, update, retract are assgigned the same Activation number.
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ */
+public interface Activation
+    extends
+    Serializable {
+    /**
+     * Retrieve the <code>Rule</code> that was activated.
+     * 
+     * @return The rule.
+     */
+    Rule getRule();
+    
+    int getSalience();
+
+    /**
+     * Retrieve the subrule that was activated.
+     * 
+     * @return
+     */
+    GroupElement getSubRule();
+
+    /**
+     * Retrieve the <code>Tuple</code> that was activated.
+     * 
+     * @return The tuple.
+     */
+    Tuple getTuple();
+
+    /**
+     * Retrieve the <code>PropagationContext</code> for the <code>Activation</code>
+     * 
+     * @return The propagation context
+     */
+    PropagationContext getPropagationContext();
+
+    /**
+     * Retrieve the activation number.
+     * 
+     * @return The activation number
+     */
+    long getActivationNumber();
+
+    /**
+     * Cancel the <code>Activation</code> by removing it from the <code>Agenda</code>. 
+     */
+    void remove();
+
+    public void addLogicalDependency(LogicalDependency node);
+
+    public LinkedList getLogicalDependencies();
+    
+    public void setLogicalDependencies(LinkedList justified);
+
+    public boolean isActivated();
+
+    public void setActivated(boolean activated);
+
+    public AgendaGroup getAgendaGroup();
+
+    public ActivationGroupNode getActivationGroupNode();
+
+    public void setActivationGroupNode(ActivationGroupNode activationGroupNode);
+
+    public RuleFlowGroupNode getRuleFlowGroupNode();
+
+    public void setRuleFlowGroupNode(RuleFlowGroupNode ruleFlowGroupNode);
+    
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ActivationGroup.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ActivationGroup.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ActivationGroup.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,22 @@
+package org.drools.spi;
+
+import java.io.Serializable;
+import java.util.Iterator;
+
+public interface ActivationGroup
+    extends
+    Serializable {
+    public String getName();
+
+    public void addActivation(Activation activation);
+
+    public void removeActivation(Activation activation);
+
+    public Iterator iterator();
+
+    public boolean isEmpty();
+
+    public int size();
+
+    public void clear();
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/AgendaFilter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/AgendaFilter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/AgendaFilter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.spi;
+
+/**
+ * @author mproctor
+ */
+public interface AgendaFilter {
+    /**
+     * Determine if a given activation should be fired.
+     * 
+     * @param activation
+     *            The activation to fire.
+     * @return <code>true</code> if the activation should be fired; otherwise
+     *         <code>false</code>
+     */
+    boolean accept(Activation activation);
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/AgendaGroup.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/AgendaGroup.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/AgendaGroup.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,64 @@
+package org.drools.spi;
+
+import java.io.Serializable;
+
+import org.drools.common.DefaultAgenda;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ *  The <code>Agenda</code> can be partitioned into groups, called <code>AgendaGroup</code>s. <code>Rule</code>s can be assigned to
+ *  these <code>AgendaGroup</code>s. Only rules in the focus group can fire. 
+ * 
+ * @see DefaultAgenda
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ *
+ */
+public interface AgendaGroup
+    extends
+    Serializable {
+
+    /**
+     * Static reference to determine the default <code>AgendaGroup</code> name.
+     */
+    public static String MAIN = "MAIN";
+
+    /**
+     * @return
+     *      The <code>AgendaGroup</code> name
+     */
+    public String getName();
+
+    /**
+     * @return An array of all the activations in the AgendaGroup
+     */
+    Activation[] getActivations();
+
+    /**
+     * The total number of activations in this group
+     * @return
+     *      int value for the total number of activations
+     */
+    public int size();
+    
+    public boolean isEmpty();
+
+    public boolean isActive();
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/AlphaNodeFieldConstraint.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/AlphaNodeFieldConstraint.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/AlphaNodeFieldConstraint.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,28 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+
+public interface AlphaNodeFieldConstraint
+    extends
+    Constraint {
+
+    public boolean isAllowed(InternalFactHandle handle,
+                             InternalWorkingMemory workingMemory);
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/AsyncExceptionHandler.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/AsyncExceptionHandler.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/AsyncExceptionHandler.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,26 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.WorkingMemory;
+
+public interface AsyncExceptionHandler {
+
+    void handleException(WorkingMemory workingMemory,
+                         ConsequenceException exception);
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/BetaNodeFieldConstraint.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/BetaNodeFieldConstraint.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/BetaNodeFieldConstraint.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,35 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.common.InternalFactHandle;
+import org.drools.reteoo.ReteTuple;
+import org.drools.rule.ContextEntry;
+
+public interface BetaNodeFieldConstraint
+    extends
+    Constraint {
+
+    public boolean isAllowedCachedLeft(ContextEntry context,
+                                       InternalFactHandle handle);
+
+    public boolean isAllowedCachedRight(ReteTuple tuple,
+                                        ContextEntry context);
+
+    public ContextEntry getContextEntry();
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/CompiledInvoker.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/CompiledInvoker.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/CompiledInvoker.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,22 @@
+package org.drools.spi;
+
+import java.util.List;
+
+/**
+ * This interface is used by semantic modules that are compiled
+ * to bytecode. 
+ * 
+ * @author Michael Neale
+ */
+public interface CompiledInvoker
+    extends
+    Invoker {
+
+    /**
+     * Generated code should be able to return a List which represents the bytecode.
+     * The elements in the list will be used to compare one semantic invoker
+     * with another by making sure each item in the list is equivalent (equals()).
+     * There are utilities in the ASM package to retrieve the bytecode for this.
+     */
+    public List getMethodBytecode();
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ConflictResolver.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ConflictResolver.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ConflictResolver.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,46 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+/**
+ * Strategy for resolving conflicts amongst multiple rules.
+ * 
+ * <p>
+ * Since a fact or set of facts may activate multiple rules, a
+ * <code>ConflictResolutionStrategy</code> is used to provide priority
+ * ordering of conflicting rules.
+ * </p>
+ * 
+ * @see Activation
+ * @see Tuple
+ * @see org.drools.rule.Rule
+ * 
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter </a>
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris </a>
+ * 
+ * @version $Id: ConflictResolver.java,v 1.1 2005/07/26 01:06:32 mproctor Exp $
+ */
+public interface ConflictResolver
+    extends
+    Serializable,
+    Comparator {
+    int compare(Activation lhs,
+                Activation rhs);
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Consequence.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Consequence.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Consequence.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,45 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.WorkingMemory;
+
+/**
+ * Consequence to be fired upon successful match of a <code>Rule</code>.
+ * 
+ * @see org.drools.rule.Rule
+ * 
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter </a>
+ */
+public interface Consequence
+    extends
+    Invoker {
+    /**
+     * Execute the consequence for the supplied matching <code>Tuple</code>.
+     * 
+     * @param activation
+     *            TODO
+     * @param workingMemory TODO
+     * @param workingMemory
+     *            The working memory session.
+     * @throws ConsequenceException
+     *             If an error occurs while attempting to invoke the
+     *             consequence.
+     */
+    void evaluate(KnowledgeHelper knowledgeHelper,
+                  WorkingMemory workingMemory) throws Exception;
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ConsequenceException.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ConsequenceException.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ConsequenceException.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,138 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.RuntimeDroolsException;
+import org.drools.rule.Rule;
+
+/**
+ * Indicates an error during a <code>Consequence</code> invocation.
+ * 
+ * @see Consequence
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ */
+public class ConsequenceException extends RuntimeDroolsException {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+    private Rule              rule;
+    private String            info;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    /**
+     * Construct.
+     */
+    public ConsequenceException() {
+        // intentionally left blank
+    }
+
+    public ConsequenceException(final String message) {
+        super( message );
+    }
+
+    /**
+     * Construct with a root cause.
+     * 
+     * @param rootCause
+     *            The root cause of this exception.
+     */
+    public ConsequenceException(final Throwable rootCause) {
+        super( rootCause );
+    }
+
+    public ConsequenceException(final Rule rule) {
+        this.rule = rule;
+    }
+
+    /**
+     * Construct with a message. Keep this from old ConsequenceException for
+     * backward compatability
+     * 
+     * @param rootCause
+     *            The root cause of this exception.
+     * 
+     * 
+     */
+    public ConsequenceException(final String message,
+                                final Rule rule) {
+        super( message );
+        this.rule = rule;
+    }
+
+    /**
+     * Construct with a root cause. Keep this from old ConsequenceException for
+     * backward compatability
+     * 
+     * @param rootCause
+     *            The root cause of this exception.
+     * 
+     * 
+     */
+    public ConsequenceException(final Throwable rootCause,
+                                final Rule rule) {
+        super( rootCause );
+        this.rule = rule;
+    }
+
+    public ConsequenceException(final String message,
+                                final Rule rule,
+                                final String info) {
+        super( message );
+        this.rule = rule;
+        this.info = info;
+    }
+
+    /**
+     * Construct with a root cause.
+     * 
+     * @param rootCause
+     *            The root cause of this exception.
+     */
+    public ConsequenceException(final Throwable rootCause,
+                                final Rule rule,
+                                final String info) {
+        super( rootCause );
+        this.rule = rule;
+        this.info = info;
+    }
+
+    public Rule getRule() {
+        return this.rule;
+    }
+
+    /**
+     * Set arbitrary extra information about the condition.
+     * 
+     * <p>
+     * The info property may be used to communicate the actual block text or
+     * other information in the case that Consequence does not have block text.
+     * </p>
+     */
+    public void setInfo(final String info) {
+        this.info = info;
+    }
+
+    public String getInfo() {
+        return this.info;
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ConsequenceExceptionHandler.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ConsequenceExceptionHandler.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ConsequenceExceptionHandler.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,15 @@
+package org.drools.spi;
+
+import java.io.Serializable;
+
+import org.drools.WorkingMemory;
+
+/**
+ * Care should be taken when implementing this class. Swallowing of consequence can be dangerous
+ * if the exception occured during a WorkingMemory action, thus leaving the integrity of the 
+ * WorkingMemory invalid.
+ *
+ */
+public interface ConsequenceExceptionHandler extends Serializable {
+    void handleException(Activation activation, WorkingMemory workingMemory, Exception exception);
+}   

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Constraint.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Constraint.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Constraint.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,49 @@
+package org.drools.spi;
+
+import org.drools.rule.Declaration;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public interface Constraint
+    extends
+    RuleComponent,
+    Cloneable {
+
+    /**
+     * Returns all the declarations required by the given 
+     * constraint implementation.
+     * 
+     * @return
+     */
+    Declaration[] getRequiredDeclarations();
+
+    /**
+     * A constraint may be required to replace an old
+     * declaration object by a new updated one
+     * 
+     * @param oldDecl
+     * @param newDecl
+     */
+    void replaceDeclaration(Declaration oldDecl,
+                            Declaration newDecl);
+
+    /**
+     * Clones the constraint
+     * @return
+     */
+    public Object clone();
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/DataProvider.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/DataProvider.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/DataProvider.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,17 @@
+package org.drools.spi;
+
+import java.io.Serializable;
+import java.util.Iterator;
+
+import org.drools.WorkingMemory;
+import org.drools.rule.Declaration;
+
+public interface DataProvider extends Serializable {
+
+    public Declaration[] getRequiredDeclarations();
+
+    public Iterator getResults(Tuple tuple,
+                               WorkingMemory wm,
+                               PropagationContext ctx);
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/DeclarationScopeResolver.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/DeclarationScopeResolver.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/DeclarationScopeResolver.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,132 @@
+package org.drools.spi;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Stack;
+
+import org.drools.rule.Pattern;
+import org.drools.rule.Declaration;
+import org.drools.rule.GroupElement;
+import org.drools.rule.RuleConditionElement;
+
+/**
+ * A class capable of resolving a declaration in the current build context
+ * 
+ * @author etirelli
+ */
+public class DeclarationScopeResolver {
+    private static final Stack EMPTY_STACK = new Stack();
+    private Map[]              maps;
+    private Stack              buildStack;
+
+    public DeclarationScopeResolver(final Map[] maps) {
+        this( maps,
+              EMPTY_STACK );
+    }
+
+    public DeclarationScopeResolver(final Map[] maps,
+                                    final Stack buildStack) {
+        this.maps = maps;
+        if ( buildStack == null ) {
+            this.buildStack = EMPTY_STACK;
+        } else {
+            this.buildStack = buildStack;
+        }
+    }
+
+    public Class getType(final String name) {
+        for ( int i = this.buildStack.size() - 1; i >= 0; i-- ) {
+            final Declaration declaration = (Declaration) ((RuleConditionElement) this.buildStack.get( i )).getInnerDeclarations().get( name );
+            if ( declaration != null ) {
+                return declaration.getExtractor().getExtractToClass();
+            }
+        }
+        for ( int i = 0, length = this.maps.length; i < length; i++ ) {
+            final Object object = this.maps[i].get( name );
+            if ( object != null ) {
+                if ( object instanceof Declaration ) {
+                    return ((Declaration) object).getExtractor().getExtractToClass();
+                } else {
+                    return (Class) object;
+                }
+            }
+        }
+        return null;
+    }
+
+    public Declaration getDeclaration(final String name) {
+        // it may be a local bound variable
+        for ( int i = this.buildStack.size() - 1; i >= 0; i-- ) {
+            final Declaration declaration = (Declaration) ((RuleConditionElement) this.buildStack.get( i )).getInnerDeclarations().get( name );
+            if ( declaration != null ) {
+                return declaration;
+            }
+        }
+        // it may be a global or something
+        for ( int i = 0, length = this.maps.length; i < length; i++ ) {
+            if ( this.maps[i].containsKey( (name) ) ) {
+                final GlobalExtractor global = new GlobalExtractor( name,
+                                                              this.maps[i] );
+                final Pattern dummy = new Pattern( 0,
+                                           global.getObjectType() );
+                final Declaration declaration = new Declaration( name,
+                                                           global,
+                                                           dummy );
+                return declaration;
+            }
+        }
+        return null;
+    }
+
+    public boolean available(final String name) {
+        for ( int i = this.buildStack.size() - 1; i >= 0; i-- ) {
+            final Declaration declaration = (Declaration) ((RuleConditionElement) this.buildStack.get( i )).getInnerDeclarations().get( name );
+            if ( declaration != null ) {
+                return true;
+            }
+        }
+        for ( int i = 0, length = this.maps.length; i < length; i++ ) {
+            if ( this.maps[i].containsKey( (name) ) ) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean isDuplicated(final String name) {
+        for ( int i = 0, length = this.maps.length; i < length; i++ ) {
+            if ( this.maps[i].containsKey( (name) ) ) {
+                return true;
+            }
+        }
+        for ( int i = this.buildStack.size() - 1; i >= 0; i-- ) {
+            final RuleConditionElement rce = (RuleConditionElement) this.buildStack.get( i );
+            final Declaration declaration = (Declaration) rce.getInnerDeclarations().get( name );
+            if ( declaration != null ) {
+                if ( (rce instanceof GroupElement) && ((GroupElement) rce).isOr() ) {
+                    // if it is an OR and it is duplicated, we can stop looking for duplication now
+                    // as it is a separate logical branch
+                    return false;
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Return all declarations scoped to the current
+     * RuleConditionElement in the build stack
+     * 
+     * @return
+     */
+    public Map getDeclarations() {
+        final Map declarations = new HashMap();
+        for ( int i = 0; i < this.buildStack.size(); i++ ) {
+            // this may be optimized in the future to only re-add elements at 
+            // scope breaks, like "NOT" and "EXISTS"
+            declarations.putAll( ((RuleConditionElement) this.buildStack.get( i )).getInnerDeclarations() );
+        }
+        return declarations;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Duration.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Duration.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Duration.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,43 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+/**
+ * Interface for specifying truthness duration.
+ * 
+ * @see org.drools.rule.Rule#setDuration
+ * @see org.drools.rule.Rule#getDuration
+ * 
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter </a>
+ */
+public interface Duration
+    extends
+    Serializable {
+    /**
+     * <p>
+     * Retrieve the duration for which the conditions of this <code>Tuple</code>
+     * must remain true before the rule will fire.
+     * </p>
+     * 
+     * @param tuple
+     * 
+     * @return the duration
+     */
+    long getDuration(Tuple tuple);
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/EvalExpression.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/EvalExpression.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/EvalExpression.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,28 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.WorkingMemory;
+import org.drools.rule.Declaration;
+
+public interface EvalExpression
+    extends
+    Invoker {
+    public boolean evaluate(Tuple tuple,
+                            Declaration[] requiredDeclarations,
+                            WorkingMemory workingMemory) throws Exception;
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Evaluator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Evaluator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Evaluator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,104 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.Operator;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.VariableRestriction.VariableContextEntry;
+
+/**
+ * A public interface to be implemented by all evaluators
+ */
+public interface Evaluator
+    extends
+    Serializable {
+
+    /**
+     * Returns the type of the values this evaluator operates upon.
+     * 
+     * @return
+     */
+    public ValueType getValueType();
+
+    /**
+     * Returns the operator representation object for this evaluator
+     * 
+     * @return
+     */
+    public Operator getOperator();
+    
+    /**
+     * Returns the value type this evaluator will coerce
+     * operands to, during evaluation. This is useful for
+     * operators like "memberOf", that always convert to
+     * Object when evaluating, independently of the source
+     * operand value type.
+     * 
+     * @return
+     */
+    public ValueType getCoercedValueType();
+
+    /**
+     * There are evaluators that operate on fact attributes and
+     * there are evaluators that operato on fact handle attributes
+     * (metadata). 
+     * 
+     * This method allows the evaluator to prepare the object
+     * to be evaluated. That includes, unwrapping the object if needed.
+     *  
+     * @param handle
+     * @return
+     */
+    public Object prepareObject( InternalFactHandle handle );
+    
+    /**
+     * This method will extract the value from the object1 using the 
+     * extractor and compare it with the object2.
+     * @param workingMemory TODO
+     * @param extractor 
+     *        The extractor used to get the source value from the object
+     * @param object1
+     *        The source object to evaluate
+     * @param object2
+     *        The actual value to compare to
+     * 
+     * @return Returns true if evaluation is successfull. false otherwise.
+     */
+    public boolean evaluate(InternalWorkingMemory workingMemory,
+                            Extractor extractor,
+                            Object object1,
+                            FieldValue value);
+
+    public boolean evaluate(InternalWorkingMemory workingMemory,
+                            Extractor leftExtractor,
+                            Object left,
+                            Extractor rightExtractor,
+                            Object right);
+
+    public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory,
+                                      VariableContextEntry context,
+                                      Object object1);
+
+    public boolean evaluateCachedRight(InternalWorkingMemory workingMemory,
+                                       VariableContextEntry context,
+                                       Object object2);
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ExecutorServiceFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ExecutorServiceFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ExecutorServiceFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,23 @@
+package org.drools.spi;
+
+import org.drools.util.ClassUtils;
+import org.drools.concurrent.ExecutorService;
+
+/** 
+ * Factory class that will return a ExecutorService based on the provided string className
+ *
+ */
+public class ExecutorServiceFactory {
+    
+    public static ExecutorService createExecutorService(String className) {        
+
+        try {
+            ExecutorService service = ( ExecutorService ) ClassUtils.instantiateObject( className );
+            
+            return service;            
+        } catch ( Throwable e ) {
+            throw new RuntimeException("Unable to instantiate ExecutorService '" + className + "'", e );
+        }        
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Extractor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Extractor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Extractor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,61 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+
+import org.drools.base.ValueType;
+import org.drools.common.InternalWorkingMemory;
+
+public interface Extractor
+    extends
+    Serializable {
+
+    public Object getValue(InternalWorkingMemory workingMemory, Object object);
+
+    public char getCharValue(InternalWorkingMemory workingMemory, Object object);
+
+    public int getIntValue(InternalWorkingMemory workingMemory, Object object);
+
+    public byte getByteValue(InternalWorkingMemory workingMemory, Object object);
+
+    public short getShortValue(InternalWorkingMemory workingMemory, Object object);
+
+    public long getLongValue(InternalWorkingMemory workingMemory, Object object);
+
+    public float getFloatValue(InternalWorkingMemory workingMemory, Object object);
+
+    public double getDoubleValue(InternalWorkingMemory workingMemory, Object object);
+
+    public boolean getBooleanValue(InternalWorkingMemory workingMemory, Object object);
+    
+    public boolean isNullValue(InternalWorkingMemory workingMemory, Object object);
+    
+    public boolean isGlobal();
+
+    public ValueType getValueType();
+
+    public Class getExtractToClass();
+
+    public String getExtractToClassName();
+
+    public Method getNativeReadMethod();
+
+    public int getHashCode(InternalWorkingMemory workingMemory, Object object);
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/FactHandleFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/FactHandleFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/FactHandleFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,61 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.drools.FactHandle;
+import org.drools.WorkingMemory;
+import org.drools.common.InternalFactHandle;
+
+/**
+ * Factory Interface to return new <code>FactHandle</code>s
+ * 
+ *  @see FactHandle
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ */
+public interface FactHandleFactory
+    extends
+    Serializable {
+   /**
+     * Construct a handle with a new id.
+     * 
+     * @return The handle.
+     */
+    InternalFactHandle newFactHandle(Object object, boolean isEvent, WorkingMemory workingMemory );
+    
+    InternalFactHandle newFactHandle(Object object, boolean isEvent, long clockTime, WorkingMemory workingMemory );
+    
+    /**
+     * Increases the recency of the FactHandle
+     * 
+     * @param factHandle
+     *      The fact handle to have its recency increased.
+     */
+    public void increaseFactHandleRecency(InternalFactHandle factHandle);
+
+    public void destroyFactHandle(InternalFactHandle factHandle);
+
+    /**
+     * @return a fresh instance of the fact handle factory, with any IDs reset etc.
+     */
+    public FactHandleFactory newInstance();
+
+    public Class getFactHandleType();
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/FieldExtractor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/FieldExtractor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/FieldExtractor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,24 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public interface FieldExtractor
+    extends
+    Extractor {
+    public int getIndex();
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/FieldValue.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/FieldValue.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/FieldValue.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,61 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+public interface FieldValue
+    extends
+    Serializable {
+
+    public Object getValue();
+
+    public char getCharValue();
+
+    public int getIntValue();
+
+    public byte getByteValue();
+
+    public short getShortValue();
+
+    public long getLongValue();
+
+    public float getFloatValue();
+
+    public double getDoubleValue();
+
+    public boolean getBooleanValue();
+    
+    public boolean isNull();
+
+    public boolean isBooleanField();
+
+    public boolean isIntegerNumberField();
+
+    public boolean isFloatNumberField();
+
+    public boolean isObjectField();
+
+    /**
+     * Returns true if the given field value implements the Collection interface
+     * @return
+     */
+    public boolean isCollectionField();
+    
+    public boolean isStringField();
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/FunctionResolver.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/FunctionResolver.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/FunctionResolver.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,17 @@
+package org.drools.spi;
+
+import java.util.List;
+
+public interface FunctionResolver {
+    public List getFunctionImports();
+
+    public void addFunctionImport(String functionImport);
+
+    public String resolveFunction(String functionName,
+                                  String params);
+
+    public String resolveFunction(String functionName,
+                                  String params,
+                                  DeclarationScopeResolver variables);
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Functions.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Functions.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Functions.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,30 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Function <code>Rule</code>.
+ * 
+ * @see org.drools.rule.Package
+ * 
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter </a>
+ */
+public interface Functions {
+    String getText();
+
+    String getSemantic();
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/GlobalExporter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/GlobalExporter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/GlobalExporter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,25 @@
+/**
+ * 
+ */
+package org.drools.spi;
+
+import java.io.Serializable;
+
+import org.drools.WorkingMemory;
+
+/**
+ * Used to provide a strategy for the StatelessSession global exportation, so that StatelessSessionResult can have accesso to
+ * globals using during the execute(...) method that returned the StatelessSessionResult.
+ *
+ */
+public interface GlobalExporter extends Serializable {
+    
+    /**
+     * This method is called internally by the StatelessSession, which will provide the WorkingMemory.
+     * The returned GlobalResolver is used by the StatefulSessionResult
+     * @param workingMemory
+     * @return
+     *       The GlobalResolver instance as used by the StatefulSessionResult
+     */
+    public GlobalResolver export(WorkingMemory workingMemory);
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/GlobalExtractor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/GlobalExtractor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/GlobalExtractor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2006 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.spi;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.ClassObjectType;
+import org.drools.base.ValueType;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.util.ClassUtils;
+
+/**
+ * This is a global variable extractor used to get a global variable value
+ * 
+ * @author etirelli
+ */
+public class GlobalExtractor
+    implements
+    Extractor {
+
+    private static final long serialVersionUID = 400L;
+    private final String            key;
+    private final ObjectType        objectType;
+
+    public GlobalExtractor(final String key,
+                           final Map map) {
+        this.key = key;
+        this.objectType = new ClassObjectType( (Class) map.get( this.key ));
+    }
+
+    public Object getValue(InternalWorkingMemory workingMemory, final Object object) {
+        return workingMemory.getGlobal( key );
+    }
+
+    public ObjectType getObjectType() {
+        return this.objectType;
+    }
+
+    public Class getExtractToClass() {
+        return this.objectType.getValueType().getClassType();
+    }
+
+    public String getExtractToClassName() {
+        return ClassUtils.canonicalName( this.objectType.getValueType().getClassType() );
+    }
+
+    public ValueType getValueType() {
+        return this.objectType.getValueType();
+    }
+
+    public boolean getBooleanValue(InternalWorkingMemory workingMemory, final Object object) {
+        if( this.objectType.getValueType().isBoolean() ) {
+            return ((Boolean) workingMemory.getGlobal( key )).booleanValue();
+        }
+        throw new ClassCastException("Not possible to convert global '"+key+"' into a boolean.");
+    }
+
+    public byte getByteValue(InternalWorkingMemory workingMemory, final Object object) {
+        if( this.objectType.getValueType().isNumber() ) {
+            return ((Number) workingMemory.getGlobal( key )).byteValue();
+        }
+        throw new ClassCastException("Not possible to convert global '"+key+"' into a byte.");
+    }
+
+    public char getCharValue(InternalWorkingMemory workingMemory, final Object object) {
+        if( this.objectType.getValueType().isChar() ) {
+            return ((Character) workingMemory.getGlobal( key )).charValue();
+        }
+        throw new ClassCastException("Not possible to convert global '"+key+"' into a char.");
+    }
+
+    public double getDoubleValue(InternalWorkingMemory workingMemory, final Object object) {
+        if( this.objectType.getValueType().isNumber() ) {
+            return ((Number) workingMemory.getGlobal( key )).doubleValue();
+        }
+        throw new ClassCastException("Not possible to convert global '"+key+"' into a double.");
+    }
+
+    public float getFloatValue(InternalWorkingMemory workingMemory, final Object object) {
+        if( this.objectType.getValueType().isNumber() ) {
+            return ((Number) workingMemory.getGlobal( key )).floatValue();
+        }
+        throw new ClassCastException("Not possible to convert global '"+key+"' into a float.");
+    }
+
+    public int getIntValue(InternalWorkingMemory workingMemory, final Object object) {
+        if( this.objectType.getValueType().isNumber() ) {
+            return ((Number) workingMemory.getGlobal( key )).intValue();
+        }
+        throw new ClassCastException("Not possible to convert global '"+key+"' into an int.");
+    }
+
+    public long getLongValue(InternalWorkingMemory workingMemory, final Object object) {
+        if( this.objectType.getValueType().isNumber() ) {
+            return ((Number) workingMemory.getGlobal( key )).longValue();
+        }
+        throw new ClassCastException("Not possible to convert global '"+key+"' into a long.");
+    }
+
+    public short getShortValue(InternalWorkingMemory workingMemory, final Object object) {
+        if( this.objectType.getValueType().isNumber() ) {
+            return ((Number) workingMemory.getGlobal( key )).shortValue();
+        }
+        throw new ClassCastException("Not possible to convert global '"+key+"' into a short.");
+    }
+
+    public Method getNativeReadMethod() {
+        try {
+            return this.getClass().getDeclaredMethod( "getValue",
+                                                      new Class[]{InternalWorkingMemory.class, Object.class} );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( "This is a bug. Please report to development team: " + e.getMessage(),
+                                              e );
+        }
+    }
+
+    public int getHashCode(InternalWorkingMemory workingMemory, final Object object) {
+        final Object value = getValue( workingMemory, object );
+        return (value != null) ? value.hashCode() : 0;
+    }
+
+    public int hashCode() {
+        return this.objectType.hashCode();
+    }
+
+    public boolean equals(final Object obj) {
+        if ( this == obj ) {
+            return true;
+        }
+        if ( !(obj instanceof GlobalExtractor) ) {
+            return false;
+        }
+        final GlobalExtractor other = (GlobalExtractor) obj;
+        return ( key == null ? other.key == null : key.equals( other.key ) ) &&
+               ( this.objectType == null ? other.objectType == null : this.objectType.equals( other.objectType ));
+    }
+
+    public boolean isNullValue( InternalWorkingMemory workingMemory, Object object ) {
+        final Object value = getValue( workingMemory, object );
+        return value == null;
+    }
+
+    public boolean isGlobal() {
+        return true;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/GlobalResolver.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/GlobalResolver.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/GlobalResolver.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,9 @@
+package org.drools.spi;
+
+import java.io.Serializable;
+
+public interface GlobalResolver extends Serializable {
+    public Object resolveGlobal(String identifier);
+    
+    public void setGlobal(String identifier, Object value);
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Invoker.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Invoker.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Invoker.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,23 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public interface Invoker
+    extends
+    RuleComponent {
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/JavaFact.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/JavaFact.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/JavaFact.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,18 @@
+package org.drools.spi;
+
+import org.drools.WorkingMemory;
+import org.drools.base.JavaFactRegistryEntry;
+
+public interface JavaFact {
+    public JavaFactRegistryEntry[] listWorkingMemories();
+
+    public boolean register(final WorkingMemory workingMemory);
+
+    public void unregisterAll();
+
+    public boolean unregister(final WorkingMemory workingMemory);
+
+    public boolean isRegistered(final WorkingMemory workingMemory);
+
+    public int[] getChanges();
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/KnowledgeHelper.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/KnowledgeHelper.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/KnowledgeHelper.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,144 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.drools.FactException;
+import org.drools.FactHandle;
+import org.drools.WorkingMemory;
+import org.drools.rule.Declaration;
+import org.drools.rule.Rule;
+
+/**
+ * KnowledgeHelper implementation types are injected into consequenses
+ * instrumented at compile time and instances passed at runtime. It provides
+ * convenience methods for users to interact with the WorkingMemory.
+ * <p>
+ * Of particular interest is the update method as it allows an object to
+ * be modified without having to specify the facthandle, because they are not
+ * passed to the consequence at runtime. To achieve this the implementation will
+ * need to lookup the fact handle of the object form the WorkingMemory.
+ * 
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter </a>
+ * @author <a href="mailto:mproctor at codehaus.org">mark proctor</a>
+ */
+public interface KnowledgeHelper
+    extends
+    Serializable {
+    
+    public void setActivation(final Activation agendaItem); 
+    
+    public void reset();
+    
+    
+    /**
+     * Asserts an object, notice that it does not return the FactHandle
+     * 
+     * @param object -
+     *            the object to be asserted
+     * @throws FactException -
+     *             Exceptions can be thrown by conditions which are wrapped and
+     *             returned as a FactException
+     */
+    void insert(Object object) throws FactException;
+    
+    /**
+     * Asserts an object specifying that it implement the onPropertyChange
+     * listener, notice that it does not return the FactHandle.
+     * 
+     * @param object -
+     *            the object to be asserted
+     * @param dynamic -
+     *            specifies the object implements onPropertyChangeListener
+     * @throws FactException -
+     *             Exceptions can be thrown by conditions which are wrapped and
+     *             returned as a FactException
+     */
+    void insert(Object object,
+                      boolean dynamic) throws FactException;
+    
+    public void insertLogical(Object object) throws FactException;
+    
+    public void insertLogical(Object object,
+                                    boolean dynamic) throws FactException;
+    
+    void update(FactHandle handle,
+                      Object newObject) throws FactException;
+
+    void update( Object newObject ) throws FactException;
+
+    void retract(FactHandle handle) throws FactException;
+
+    void retract(Object object) throws FactException;
+    
+    public void modifyRetract(final Object object);
+    
+    public void modifyRetract(final FactHandle factHandle);
+
+    public void modifyInsert(final Object object); 
+    
+    public void modifyInsert(final FactHandle factHandle,
+                             final Object object);     
+    
+    public Object get(Declaration declaration);
+
+    /**
+     * @return - The rule name
+     */
+    Rule getRule();
+
+    Tuple getTuple();
+
+    Activation getActivation();
+
+    WorkingMemory getWorkingMemory();
+
+//    /** @return - A List of the objects in the WorkingMemory */
+//    List getObjects();
+//
+//    /**
+//     * Retruns a List of Objects that match the given Class in the paremeter.
+//     * 
+//     * @param objectClass -
+//     *            The Class to filter by
+//     * @return - All the Objects in the WorkingMemory that match the given Class
+//     *         filter
+//     */
+//    List getObjects(Class objectClass);
+//
+//    QueryResults getQueryResults(String query);
+//
+//    /**
+//     * Clears the agenda causing all existing Activations to fire
+//     * ActivationCancelled events. <br>
+//     */
+//    void clearAgenda();
+//
+//    void clearAgendaGroup(String group);
+//
+//    public AgendaGroup getFocus();
+//
+    void setFocus(String focus);
+//
+//    void setFocus(AgendaGroup focus);
+
+    public Declaration getDeclaration(String identifier);
+    
+    public void halt();
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ObjectType.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ObjectType.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ObjectType.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,57 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.drools.base.ValueType;
+
+/**
+ * Semantic object type differentiator.
+ * 
+ * @see org.drools.rule.Declaration
+ * 
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter </a>
+ */
+public interface ObjectType
+    extends
+    Serializable {
+    /**
+     * Determine if the passed <code>Object</code> belongs to the object type
+     * defined by this <code>objectType</code> instance.
+     * 
+     * @param object
+     *            The <code>Object</code> to test.
+     * 
+     * @return <code>true</code> if the <code>Object</code> matches this
+     *         object type, else <code>false</code>.
+     */
+    boolean matches(Object object);
+    
+    boolean isAssignableFrom(Object object);
+    
+    boolean isAssignableFrom(ObjectType objectType);
+    
+    /**
+     * Returns true if the object type represented by this object
+     * is an event object type. False otherwise.
+     * @return
+     */
+    boolean isEvent();
+
+    ValueType getValueType();
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/PatternExtractor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/PatternExtractor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/PatternExtractor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,171 @@
+package org.drools.spi;
+
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.ClassObjectType;
+import org.drools.base.ShadowProxy;
+import org.drools.base.ValueType;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.facttemplates.Fact;
+import org.drools.util.ClassUtils;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class PatternExtractor
+    implements
+    Extractor {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+    private ObjectType        objectType;
+
+    public PatternExtractor(final ObjectType objectType) {
+        this.objectType = objectType;
+    }
+
+    public Object getValue(InternalWorkingMemory workingMemory, final Object object) {
+        // need to use instanceof because an object may be created in nodes like accumulate and from
+        // where no shadow is applied
+        return (object instanceof ShadowProxy) ? ((ShadowProxy) object).getShadowedObject() : object;
+    }
+
+    public ObjectType getObjectType() {
+        return this.objectType;
+    }
+
+    public Class getExtractToClass() {
+        // @todo : this is a bit nasty, but does the trick
+        if ( this.objectType instanceof ClassObjectType ) {
+            return ((ClassObjectType) this.objectType).getClassType();
+        } else {
+            return Fact.class;
+        }
+    }
+
+    public String getExtractToClassName() {
+        Class clazz = null;
+        // @todo : this is a bit nasty, but does the trick
+        if ( this.objectType instanceof ClassObjectType ) {
+            clazz = ((ClassObjectType) this.objectType).getClassType();
+        } else {
+            clazz = Fact.class;
+        }
+        return ClassUtils.canonicalName( clazz );
+    }
+
+    public ValueType getValueType() {
+        return this.objectType.getValueType();
+    }
+
+    public boolean getBooleanValue(InternalWorkingMemory workingMemory, final Object object) {
+        if ( this.objectType.getValueType().isBoolean() ) {
+            return ((Boolean) object).booleanValue();
+        }
+        throw new RuntimeDroolsException( "Conversion to boolean not supported for type: " + object.getClass() );
+    }
+
+    public byte getByteValue(InternalWorkingMemory workingMemory, final Object object) {
+        if ( this.objectType.getValueType().isNumber() ) {
+            return ((Number) object).byteValue();
+        }
+        throw new RuntimeDroolsException( "Conversion to byte not supported for type: " + object.getClass() );
+    }
+
+    public char getCharValue(InternalWorkingMemory workingMemory, final Object object) {
+        if ( this.objectType.getValueType().isChar() ) {
+            return ((Character) object).charValue();
+        }
+        throw new RuntimeDroolsException( "Conversion to char not supported for type: " + object.getClass() );
+    }
+
+    public double getDoubleValue(InternalWorkingMemory workingMemory, final Object object) {
+        if ( this.objectType.getValueType().isNumber() ) {
+            return ((Number) object).doubleValue();
+        }
+        throw new RuntimeDroolsException( "Conversion to double not supported for type: " + object.getClass() );
+    }
+
+    public float getFloatValue(InternalWorkingMemory workingMemory, final Object object) {
+        if ( this.objectType.getValueType().isNumber() ) {
+            return ((Number) object).floatValue();
+        }
+        throw new RuntimeDroolsException( "Conversion to float not supported for type: " + object.getClass() );
+    }
+
+    public int getIntValue(InternalWorkingMemory workingMemory, final Object object) {
+        if ( this.objectType.getValueType().isNumber() ) {
+            return ((Number) object).intValue();
+        }
+        throw new RuntimeDroolsException( "Conversion to int not supported for type: " + object.getClass() );
+    }
+
+    public long getLongValue(InternalWorkingMemory workingMemory, final Object object) {
+        if ( this.objectType.getValueType().isNumber() ) {
+            return ((Number) object).longValue();
+        }
+        throw new RuntimeDroolsException( "Conversion to long not supported for type: " + object.getClass() );
+    }
+
+    public short getShortValue(InternalWorkingMemory workingMemory, final Object object) {
+        if ( this.objectType.getValueType().isNumber() ) {
+            return ((Number) object).shortValue();
+        }
+        throw new RuntimeDroolsException( "Conversion to short not supported for type: " + object.getClass() );
+    }
+
+    public Method getNativeReadMethod() {
+        try {
+            return this.getClass().getDeclaredMethod( "getValue",
+                                                      new Class[]{InternalWorkingMemory.class, Object.class} );
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( "This is a bug. Please report to development team: " + e.getMessage(),
+                                              e );
+        }
+    }
+
+    public boolean isNullValue(InternalWorkingMemory workingMemory, final Object object ) {
+        return getValue( workingMemory, object ) == null;
+    }
+
+    public int getHashCode(InternalWorkingMemory workingMemory, final Object object) {
+        return getValue( workingMemory, object ).hashCode();
+    }
+
+    public int hashCode() {
+        return this.objectType.hashCode();
+    }
+
+    public boolean equals(final Object obj) {
+        if ( this == obj ) {
+            return true;
+        }
+        if ( !(obj instanceof PatternExtractor) ) {
+            return false;
+        }
+        final PatternExtractor other = (PatternExtractor) obj;
+        return this.objectType.equals( other.objectType );
+    }
+
+    public boolean isGlobal() {
+        return false;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/PredicateExpression.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/PredicateExpression.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/PredicateExpression.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,30 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.WorkingMemory;
+import org.drools.rule.Declaration;
+
+public interface PredicateExpression
+    extends
+    Invoker {
+    public boolean evaluate(Object object,
+                            Tuple tuple,
+                            Declaration[] previousDeclarations,
+                            Declaration[] localDeclarations,
+                            WorkingMemory workingMemory) throws Exception;
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/PropagationContext.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/PropagationContext.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/PropagationContext.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,60 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import org.drools.reteoo.ReteTuple;
+import org.drools.rule.EntryPoint;
+import org.drools.rule.Rule;
+
+public interface PropagationContext
+    extends
+    Serializable {
+
+    public static final int ASSERTION     = 0;
+    public static final int RETRACTION    = 1;
+    public static final int MODIFICATION  = 2;
+    public static final int RULE_ADDITION = 3;
+    public static final int RULE_REMOVAL  = 4;
+
+    public long getPropagationNumber();
+
+    public Rule getRuleOrigin();
+
+    public Activation getActivationOrigin();
+    
+    //public int setType(int type);
+
+    public int getType();
+
+    public int getActiveActivations();
+
+    public int getDormantActivations();
+
+    public void addRetractedTuple(Rule rule,
+                                  Activation activation);
+
+    public Activation removeRetractedTuple(Rule rule,
+                                           ReteTuple tuple);
+
+    public void clearRetractedTuples();
+    
+    public void releaseResources();
+    
+    public EntryPoint getEntryPoint();
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Restriction.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Restriction.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Restriction.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,41 @@
+package org.drools.spi;
+
+import java.io.Serializable;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.rule.ContextEntry;
+import org.drools.rule.Declaration;
+
+public interface Restriction
+    extends
+    Serializable,
+    Cloneable {
+    Declaration[] getRequiredDeclarations();
+
+    public boolean isAllowed(Extractor extractor,
+                             InternalFactHandle handle,
+                             InternalWorkingMemory workingMemory);
+
+    public boolean isAllowedCachedLeft(ContextEntry context,
+                                       InternalFactHandle handle);
+
+    public boolean isAllowedCachedRight(ReteTuple tuple,
+                                        ContextEntry context);
+
+    public ContextEntry getContextEntry();
+
+    /**
+     * A restriction may be required to replace an old
+     * declaration object by a new updated one
+     * 
+     * @param oldDecl
+     * @param newDecl
+     */
+    void replaceDeclaration(Declaration oldDecl,
+                            Declaration newDecl);
+
+    public Object clone();
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ReturnValueEvaluator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ReturnValueEvaluator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ReturnValueEvaluator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,7 @@
+package org.drools.spi;
+
+import org.drools.WorkingMemory;
+
+public interface ReturnValueEvaluator {
+    Object evaluate(WorkingMemory workingMemory) throws Exception;
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ReturnValueExpression.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ReturnValueExpression.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/ReturnValueExpression.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,30 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.WorkingMemory;
+import org.drools.rule.Declaration;
+
+public interface ReturnValueExpression
+    extends
+    Invoker {
+    public FieldValue evaluate(Object object,
+                               Tuple tuple,
+                               Declaration[] previousDeclarations,
+                               Declaration[] localDeclarations,
+                               WorkingMemory workingMemory) throws Exception;
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/RuleBaseUpdateListener.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/RuleBaseUpdateListener.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/RuleBaseUpdateListener.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,11 @@
+/**
+ * 
+ */
+package org.drools.spi;
+
+import org.drools.StatefulSession;
+import org.drools.event.RuleBaseEventListener;
+
+public interface RuleBaseUpdateListener extends RuleBaseEventListener {
+    public void setSession(StatefulSession session);
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/RuleBaseUpdateListenerFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/RuleBaseUpdateListenerFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/RuleBaseUpdateListenerFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,26 @@
+package org.drools.spi;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.StatefulSession;
+import org.drools.util.ClassUtils;
+
+/** 
+ * Factory class that will return a RuleBaseUpdateListener based on the provided string className
+ *
+ */
+public class RuleBaseUpdateListenerFactory {
+    
+    public static RuleBaseUpdateListener createListener(String className, StatefulSession session) {        
+        try {
+            RuleBaseUpdateListener listener = ( RuleBaseUpdateListener ) ClassUtils.instantiateObject( className );
+            listener.setSession( session );
+            
+            return listener;            
+        } catch ( Throwable e ) {
+            throw new RuntimeException("Unable to instantiate RuleBaseUpdateListener '" + className + "'", e );
+        }        
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/RuleComponent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/RuleComponent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/RuleComponent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,32 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+/**
+ * Semantic component marker.
+ * 
+ * @author <a href="mailto:bob at werken.com">bob mcwhirter </a>
+ * 
+ * @version $Id$
+ */
+public interface RuleComponent
+    extends
+    Serializable {
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/RuleFlowGroup.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/RuleFlowGroup.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/RuleFlowGroup.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,43 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.Iterator;
+
+public interface RuleFlowGroup extends Serializable {
+
+    String getName();
+
+    public Iterator iterator();
+
+    boolean isEmpty();
+
+    int size();
+
+    boolean isActive();
+
+    boolean isAutoDeactivate();
+
+    /**
+     * Sets the auto-deactivate status of this RuleFlowGroup.
+     * If this is set to true, an active RuleFlowGroup automatically
+     * deactivates if it has no more activations.  If it had no
+     * activations when it was activated, it will be deactivated immediately. 
+     */
+    void setAutoDeactivate(boolean autoDeactivate);
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Salience.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Salience.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Salience.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,10 @@
+package org.drools.spi;
+
+import java.io.Serializable;
+
+import org.drools.WorkingMemory;
+
+public interface Salience extends Serializable {    
+    public int getValue(final Tuple tuple,
+                        final WorkingMemory workingMemory);
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Tuple.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Tuple.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/spi/Tuple.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,77 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.drools.common.EventFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.rule.Declaration;
+
+/**
+ * Partial matches are propagated through the Rete network as <code>Tuple</code>s. Each <code>Tuple</code>
+ * Is able to return the <code>FactHandleImpl</code> members of the partial match for the requested pattern.
+ * The pattern refers to the index position of the <code>FactHandleImpl</code> in the underlying implementation.
+ * 
+ * @see FactHandle;
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ *
+ */
+public interface Tuple
+    extends
+    Serializable {
+    /**
+     * Returns the <code>FactHandle</code> for the given pattern index. If the pattern is empty
+     * It returns null.
+     * 
+     * @param pattern
+     *      The index of the pattern from which the <code>FactHandleImpl</code> is to be returned
+     * @return
+     *      The <code>FactHandle</code>
+     */
+    InternalFactHandle get(int pattern);
+
+    /**
+     * Returns the <code>FactHandle</code> for the given <code>Declaration</code>, which in turn
+     * specifcy the <code>Pattern</code> that they depend on.
+     * 
+     * @param declaration
+     *      The <code>Declaration</code> which specifies the <code>Pattern</code>
+     * @return
+     *      The <code>FactHandle</code>
+     */
+    InternalFactHandle get(Declaration declaration);
+
+    InternalFactHandle[] getFactHandles();
+
+    boolean containsEvents();
+    
+    /**
+     * Returns the tuple recency
+     * @return
+     */
+    long getRecency();
+
+    /**
+     * Returns the size of this tuple in number of elements (patterns)
+     * @return
+     */
+    int size();
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/AbstractSessionClock.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/AbstractSessionClock.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/AbstractSessionClock.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,81 @@
+package org.drools.temporal;
+
+public abstract class AbstractSessionClock
+		implements SessionClock {
+	
+	/*@ Override
+	public void addObserver (Observer o){
+		super.addObserver(o);
+		setChanged();
+        notifyObservers();
+	}*/
+	
+	public abstract void jumpTo (long time);
+	
+	 // using current system time as reference
+    public long calcFuturePointInTime (long timeToAdd){
+    	return getCurrentTime()+timeToAdd;
+    }
+    
+    // ------------------------------------------------------------------------------------
+    // static convenience methods
+    
+    // using an arbitrary starting point as reference
+    public static long calcFuturePointInTime (long currentTime, long timeToAdd){
+    	return currentTime+timeToAdd;
+	}
+    
+    // convert seconds to milliseconds
+	public static long timeInSeconds (long timeInSecs){
+		return timeInSecs*1000;
+	}
+	
+	// convert seconds to milliseconds
+	public static long timeInMinutes (long timeInMins){
+		return timeInSeconds(timeInMins)*60;
+	}
+	
+	// convert seconds to milliseconds
+	public static long timeInHours (long timeInHrs){
+		return timeInMinutes(timeInHrs)*60;
+	}
+	
+	// convert time given as hours, minutes, seconds, milliseconds to milliseconds
+	public static long timeinHMSM (long hours, long mins, long secs, long msecs){
+		return timeInHours(hours) + timeInMinutes(mins) + timeInSeconds(secs) + msecs;
+	}
+	
+	// expects givenTime to be in millisecs
+	public static String millisecsToString(long givenTime){
+		String result;
+		long h, min, sec, ms;
+		long temp;
+		
+		// extract milliseconds
+		temp = givenTime;
+		ms = temp%1000; 
+		result = ((ms < 10)? "0" : "") + ((ms < 100)? "0" : "") + ms;
+		
+		// extract seconds
+		temp = (temp-ms)/1000;
+		sec = temp%60;
+		result = ((sec < 10)? "0" : "") + sec + "." + result;
+		
+		// extract minutes
+		temp = (temp-sec)/60;
+		min = temp%60;
+		result = ((min < 10)? "0" : "") + min + ":" + result;
+		
+		// extract hours
+		temp = (temp-min)/60;
+		h = temp%24;
+		result = ((h < 10)? "0" : "") + h + ":" + result;
+		
+		return result;
+	}
+	
+	public String toString(){
+		return millisecsToString(getCurrentTime());
+	}
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/EventExpiration.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/EventExpiration.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/EventExpiration.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,57 @@
+package org.drools.temporal;
+
+import org.drools.spi.Tuple;
+
+public class EventExpiration<T> {
+	
+	private final T event;
+	private final long expires; 
+	//private PropagationContext context;
+	private final boolean ofTypeTuple;
+	
+	public EventExpiration(final T event, final boolean isTuple, final long expires/*, PropagationContext context*/) {
+		this.event = event;
+		this.ofTypeTuple = isTuple;
+		this.expires = expires;
+		//this.context = context;
+		
+		//System.out.println (this.toString());
+	}
+
+	public EventExpiration(final T event, final long expires/*, PropagationContext context*/) {
+		this(event, (event instanceof Tuple), expires);
+	}
+	
+	/**
+	 * @return the tuple
+	 */
+	public T getEvent() {
+		return event;
+	}
+	
+/*	*//**
+	 * @param type the new context type
+	 *//*
+	public void changePropagationContext (final int type){
+		this.context.setType(type);
+	}*/
+
+	/**
+	 * @return the expires
+	 */
+	public long getExpires() {
+		return expires;
+	}
+
+	/**
+	 * @return Returns true if item is of type Tuple, false if it is of type EventFactHandle
+	 */
+	public boolean isOfTypeTuple() {
+		return ofTypeTuple;
+	}
+	
+	public String toString(){
+		return event.toString()+ " expires at "+AbstractSessionClock.millisecsToString(expires);
+	}
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/GlobalSessionClockImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/GlobalSessionClockImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/GlobalSessionClockImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,33 @@
+package org.drools.temporal;
+
+import org.drools.ClockType;
+
+public final class GlobalSessionClockImpl {
+
+	/** Singleton pattern: private class attribute, create single instance of the class. */
+    private static SessionClock INSTANCE;
+
+    /** Singleton pattern: private constructor, no instantiation from outside */ 
+    private GlobalSessionClockImpl() {
+    }
+    /** Singleton pattern: static method "createInstance()" creates instance with parameter, but only once. */
+    public static synchronized SessionClock createInstance(ClockType type) {
+        if (INSTANCE == null) {
+            INSTANCE = type.createInstance();
+        } else {
+            throw new UnsupportedOperationException("Instance already created!");
+        }
+        //System.out.println ("Instantiated global session clock of type "+type.getDeclaringClass().getName());
+        return INSTANCE;
+    }
+ 
+    /** Singleton pattern: static method "getInstance()" returns single instance of the class. */
+    public static synchronized SessionClock getInstance() {
+        if (INSTANCE != null) {
+            return INSTANCE;
+        } else {
+            throw new UnsupportedOperationException("Create instance with desired clock type as parameter first!");
+        }
+    }
+	
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/SessionClock.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/SessionClock.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/SessionClock.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Oct 17, 2007
+ */
+package org.drools.temporal;
+
+/**
+ * A clock interface that all engine clocks must implement
+ * 
+ * @author mgroch
+ */
+public interface SessionClock {
+    
+    /**
+     * Returns the current time. There is no semantics attached
+     * to the long return value, so it will depend on the actual
+     * implementation. For isntance, for a real clock it may be
+     * milliseconds.
+     * 
+     * @return The current time. The unit of the time, depends on
+     * the actual clock implementation.
+     * 
+     */
+    public long getCurrentTime();
+    
+    public String toString();
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/SessionPseudoClock.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/SessionPseudoClock.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/SessionPseudoClock.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Oct 17, 2007
+ */
+package org.drools.temporal;
+
+import org.apache.log4j.Logger;
+
+/**
+ * A SessionPseudoClock is a clock that allows the user to explicitly 
+ * control current time.
+ * 
+ * @author etirelli
+ *
+ */
+public class SessionPseudoClock extends
+    AbstractSessionClock {
+
+	private final Logger myLogger = Logger.getLogger(SessionPseudoClock.class.getName());
+  
+    private long timer;
+
+    public SessionPseudoClock() {
+        this.timer = 0; 
+        //System.out.println ("SessionPseudoClock: Jetzt initialisiert");
+    }
+    
+    /* (non-Javadoc)
+     * @see org.drools.temporal.SessionClock#getCurrentTime()
+     */
+    public long getCurrentTime() {
+        return this.timer;
+    }
+    
+    public long advanceTime( long millisecs ) {
+        this.timer += millisecs;
+        //setChanged();
+        //notifyObservers();
+        myLogger.info ("\nTime advanced. Current time is "+this.toString());
+        /*try {
+			Thread.sleep(millisecs/1000);
+		} catch (InterruptedException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}*/
+        return this.timer;
+    }
+
+    @Override
+    public void jumpTo( long timer ) {
+        this.timer = timer;
+        //setChanged();
+        //notifyObservers();
+        //return this.timer;
+    }
+   
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/SessionSystemClock.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/SessionSystemClock.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/temporal/SessionSystemClock.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,72 @@
+
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Oct 17, 2007
+ */
+package org.drools.temporal;
+
+import org.apache.log4j.Logger;
+
+/**
+ * A System clock is a clock that returns the time based on the underlying
+ * system clock. It is usually used for real time applications
+ * 
+ * @author mgroch
+ *
+ */
+public final class SessionSystemClock extends
+    AbstractSessionClock {
+	
+	private final int FACTOR = 1000;
+	private final long startTime;
+	
+	private final Logger myLogger = Logger.getLogger(SessionPseudoClock.class.getName());
+	
+    /* (non-Javadoc)
+     * @see org.drools.temporal.SessionClock#getCurrentTime()
+     */
+	
+	public SessionSystemClock (){
+		this.startTime = System.currentTimeMillis();
+	}
+	
+    public long getCurrentTime() {
+        return (System.currentTimeMillis()-startTime)*FACTOR;
+    }
+    
+    public void advanceTime( long millisecs ) {
+    
+        myLogger.info ("\nTime advanced. Current time is "+this.toString());
+        try {
+			Thread.sleep(millisecs/FACTOR);
+		} catch (InterruptedException e) {
+			e.printStackTrace();
+		}
+    }
+    
+    @Override
+    public void jumpTo (long timer){
+    	long timeToWait = timer - this.getCurrentTime();
+    	myLogger.debug("Send event generating thread for "+timeToWait/FACTOR+" ms to sleep.");
+    	if (timeToWait > 0)
+	    	try {
+				Thread.sleep(timeToWait/FACTOR);
+			} catch (InterruptedException e) {
+				e.printStackTrace();
+			}
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/AbstractBaseLinkedListNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/AbstractBaseLinkedListNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/AbstractBaseLinkedListNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,70 @@
+package org.drools.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Provides a abstract base implementation that an object can extend so that it can be used in a LinkedList.
+ * 
+ * @see LinkedList
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ */
+public class AbstractBaseLinkedListNode
+    implements
+    LinkedListNode {
+
+    private static final long serialVersionUID = 400L;
+
+    private LinkedListNode    previous;
+
+    private LinkedListNode    next;
+
+    /**
+     * Empty Constructor
+     */
+    public AbstractBaseLinkedListNode() {
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.LinkedListNode#getNext()
+     */
+    public LinkedListNode getNext() {
+        return this.next;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.LinkedListNode#setNext(org.drools.reteoo.LinkedListNode)
+     */
+    public void setNext(final LinkedListNode next) {
+        this.next = next;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.LinkedListNode#getPrevious()
+     */
+    public LinkedListNode getPrevious() {
+        return this.previous;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.LinkedListNode#setPrevious(org.drools.reteoo.LinkedListNode)
+     */
+    public void setPrevious(final LinkedListNode previous) {
+        this.previous = previous;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/AbstractHashTable.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/AbstractHashTable.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/AbstractHashTable.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,741 @@
+/**
+ * 
+ */
+package org.drools.util;
+
+import java.io.Serializable;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.reteoo.ReteTuple;
+import org.drools.rule.Declaration;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldExtractor;
+
+public abstract class AbstractHashTable
+    implements
+    Serializable {
+    static final int           MAX_CAPACITY = 1 << 30;
+
+    protected int              size;
+    protected int              threshold;
+    protected float            loadFactor;
+
+    protected ObjectComparator comparator;
+
+    protected Entry[]          table;
+
+    private HashTableIterator  iterator;
+
+    public AbstractHashTable() {
+        this( 16,
+              0.75f );
+    }
+    
+    public AbstractHashTable(final int capacity,
+                             final float loadFactor) {
+        this.loadFactor = loadFactor;
+        this.threshold = (int) (capacity * loadFactor);
+        this.table = new Entry[capacity];
+        this.comparator = EqualityEquals.getInstance();
+    }
+    
+    public AbstractHashTable(final Entry[] table) {
+        this( 0.75f, table);
+    }      
+    
+    public AbstractHashTable(final float loadFactor,
+                             final Entry[] table) {
+        this.loadFactor = loadFactor;
+        this.threshold = (int) (table.length * loadFactor);
+        this.table = table;
+        this.comparator = EqualityEquals.getInstance();
+    }    
+
+    public Iterator iterator() {
+        if ( this.iterator == null ) {
+            this.iterator = new HashTableIterator( this );
+        }
+
+        this.iterator.reset();
+        return this.iterator;
+    }
+    
+    public Iterator newIterator() {
+        HashTableIterator iterator = new HashTableIterator( this );
+        iterator.reset();
+        return iterator;
+        
+    }
+
+    public void setComparator(final ObjectComparator comparator) {
+        this.comparator = comparator;
+    }
+
+    protected void resize(final int newCapacity) {
+        final Entry[] oldTable = this.table;
+        final int oldCapacity = oldTable.length;
+        if ( oldCapacity == AbstractHashTable.MAX_CAPACITY ) {
+            this.threshold = Integer.MAX_VALUE;
+            return;
+        }
+
+        final Entry[] newTable = new Entry[newCapacity];
+
+        for ( int i = 0; i < this.table.length; i++ ) {
+            Entry entry = this.table[i];
+            if ( entry == null ) {
+                continue;
+            }
+            this.table[i] = null;
+            Entry next = null;
+            while ( entry != null ) {
+                next = entry.getNext();
+
+                final int index = indexOf( entry.hashCode(),
+                                           newTable.length );
+                entry.setNext( newTable[index] );
+                newTable[index] = entry;
+
+                entry = next;
+            }
+        }
+
+        this.table = newTable;
+        this.threshold = (int) (newCapacity * this.loadFactor);
+    }     
+    
+    public Entry[] toArray() {
+        Entry[] result = new Entry[this.size];
+        int index = 0;
+        for ( int i = 0; i < this.table.length; i++ ) {
+            Entry entry = this.table[i];
+            while ( entry != null ) {
+                result[index++] = entry;
+                entry = entry.getNext();
+            }
+        }
+        return result;
+    }
+
+    //    public void add(Entry entry) {
+    //        int index = indexOf( entry.hashCode(), table.length  );
+    //
+    //        
+    //        boolean exists = false;
+    //        
+    //        // scan the linked entries to see if it exists
+    //        if ( !checkExists ) {
+    //            Entry current = this.table[index];
+    //            int hashCode = entry.hashCode();
+    //            while ( current != null ) {                
+    //                if  ( hashCode == current.hashCode() && entry.equals( current ) ) {
+    //                    exists = true;
+    //                }
+    //            }                        
+    //        }
+    //        
+    //        if( exists == false ) {
+    //            entry.setNext( this.table[index] );
+    //            this.table[index] = entry;
+    //    
+    //            if ( this.size++ >= this.threshold ) {
+    //                resize( 2 * this.table.length );
+    //            }
+    //        }
+    //
+    //    }
+    //
+    //    public Entry get(Entry entry) {
+    //        int index = indexOf( entry.hashCode(), table.length  );
+    //        Entry current = this.table[index];
+    //        while ( current != null ) {
+    //            if ( entry.hashCode() == current.hashCode() && entry.equals( current ) ) {
+    //                return current;
+    //            }
+    //            current = current.getNext();
+    //        }
+    //        return null;
+    //    }
+    //
+    //    public Entry remove(Entry entry) {
+    //        int index = indexOf( entry.hashCode(), table.length  );
+    //        Entry previous = this.table[index];        
+    //        Entry current = previous;
+    //        int hashCode = entry.hashCode();
+    //        while ( current != null ) {
+    //            Entry next = current.getNext();
+    //            if ( hashCode == current.hashCode() && entry.equals( current ) ) {
+    //                if( previous  == current ) {
+    //                    this.table[index] = next;
+    //                    previous.setNext( next );
+    //                }
+    //                current.setNext( null );
+    //                this.size--;
+    //                return current;
+    //            }
+    //            previous = current;
+    //            current = next;
+    //        }
+    //        return current;
+    //    }
+
+    protected Entry getBucket(final int hashCode) {
+        return this.table[indexOf( hashCode,
+                                   this.table.length )];
+    }
+
+    public Entry[] getTable() {
+        return this.table;
+    }
+
+    public int size() {
+        return this.size;
+    }
+
+    public boolean isEmpty() {
+        return this.size == 0;
+    }
+
+    //    protected int indexOf(int hashCode,
+    //                          int dataSize) {
+    //        int index = hashCode % dataSize;
+    //        if ( index < 0 ) {
+    //            index = index * -1;
+    //        }
+    //        return index;
+    //    }
+
+    protected int indexOf(final int hashCode,
+                          final int dataSize) {
+        return hashCode & (dataSize - 1);
+    }
+
+    public abstract Entry getBucket(Object object);
+
+    public interface ObjectComparator
+        extends
+        Serializable {
+        public int hashCodeOf(Object object);
+
+        public int rehash(int hashCode);
+
+        public boolean equal(Object object1,
+                             Object object2);
+    }
+
+    /**
+     * Fast re-usable iterator
+     *
+     */
+    public static class HashTableIterator
+        implements
+        Iterator {
+
+        private static final long serialVersionUID = 400L;
+
+        private AbstractHashTable hashTable;
+        private Entry[]           table;
+        private int               row;
+        private int               length;
+        private Entry             entry;
+
+        public HashTableIterator(final AbstractHashTable hashTable) {
+            this.hashTable = hashTable;
+        }
+
+        /* (non-Javadoc)
+         * @see org.drools.util.Iterator#next()
+         */
+        public Object next() {
+            if ( this.entry == null ) {
+                // keep skipping rows until we come to the end, or find one that is populated
+                while ( this.entry == null ) {
+                    this.row++;
+                    if ( this.row == this.length ) {
+                        return null;
+                    }
+                    this.entry = this.table[this.row];
+                }
+            } else {
+                this.entry = this.entry.getNext();
+                if ( this.entry == null ) {
+                    this.entry = (Entry) next();
+                }
+            }
+
+            return this.entry;
+        }
+
+        /* (non-Javadoc)
+         * @see org.drools.util.Iterator#reset()
+         */
+        public void reset() {
+            this.table = this.hashTable.getTable();
+            this.length = this.table.length;
+            this.row = -1;
+            this.entry = null;
+        }
+    }
+
+    public static class InstanceEquals
+        implements
+        ObjectComparator {
+
+        private static final long      serialVersionUID = 400L;
+        public static ObjectComparator INSTANCE         = new InstanceEquals();
+
+        public static ObjectComparator getInstance() {
+            return InstanceEquals.INSTANCE;
+        }
+
+        public int hashCodeOf(final Object key) {
+            return rehash( key.hashCode() );
+        }
+
+        public int rehash(int h) {
+            h += ~(h << 9);
+            h ^= (h >>> 14);
+            h += (h << 4);
+            h ^= (h >>> 10);
+            return h;
+        }
+
+        private InstanceEquals() {
+
+        }
+
+        public boolean equal(final Object object1,
+                             final Object object2) {
+            return object1 == object2;
+        }
+    }
+
+    public static class EqualityEquals
+        implements
+        ObjectComparator {
+
+        private static final long      serialVersionUID = 400L;
+        public static ObjectComparator INSTANCE         = new EqualityEquals();
+
+        public static ObjectComparator getInstance() {
+            return EqualityEquals.INSTANCE;
+        }
+
+        public int hashCodeOf(final Object key) {
+            return rehash( key.hashCode() );
+        }
+
+        public int rehash(int h) {
+            h += ~(h << 9);
+            h ^= (h >>> 14);
+            h += (h << 4);
+            h ^= (h >>> 10);
+            return h;
+        }
+
+        private EqualityEquals() {
+
+        }
+
+        public boolean equal(final Object object1,
+                             final Object object2) {
+            if ( object1 == null ) {
+                return object2 == null;
+            }
+            return object1.equals( object2 );
+        }
+    }
+
+    public static class FactEntryImpl
+        implements
+        FactEntry,
+        Entry {
+
+        private static final long serialVersionUID = 400L;
+
+        public InternalFactHandle handle;
+
+        public int                hashCode;
+
+        public Entry              next;
+
+        //        private LinkedList              list;
+
+        public FactEntryImpl(final InternalFactHandle handle) {
+            this.handle = handle;
+            this.hashCode = handle.hashCode();
+            //            this.list = new LinkedList();
+        }
+
+        public FactEntryImpl(final InternalFactHandle handle,
+                         final int hashCode) {
+            this.handle = handle;
+            this.hashCode = hashCode;
+            //            this.list = new LinkedList();
+        }
+
+        public InternalFactHandle getFactHandle() {
+            return this.handle;
+        }
+
+        public Entry getNext() {
+            return this.next;
+        }
+
+        public void setNext(final Entry next) {
+            this.next = next;
+        }
+
+        //        
+        //        void add(final LinkedListEntry tupleMatchEntry) {
+        //            this.list.add( tupleMatchEntry );
+        //        }
+        //        void remove(final LinkedListEntry tupleMatchEntry) {
+        //            this.list.remove( tupleMatchEntry );
+        //        }        
+
+        public int hashCode() {
+            return this.hashCode;
+        }
+
+        public boolean equals(final Object object) {
+            return (object == this) || (this.handle == ((FactEntryImpl) object).handle);
+        }
+
+        public String toString() {
+            return "FactEntry( handle=" + this.handle + " hashcode=" + this.hashCode + " next=" + this.next + " )";
+        }
+    }
+
+    public static class FieldIndex {
+        FieldExtractor   extractor;
+        Declaration      declaration;
+        public Evaluator evaluator;
+
+        public FieldIndex(final FieldExtractor extractor,
+                          final Declaration declaration,
+                          final Evaluator evaluator) {
+            super();
+            this.extractor = extractor;
+            this.declaration = declaration;
+            this.evaluator = evaluator;
+        }
+
+        public Declaration getDeclaration() {
+            return this.declaration;
+        }
+
+        public FieldExtractor getExtractor() {
+            return this.extractor;
+        }
+
+        public Evaluator getEvaluator() {
+            return this.evaluator;
+        }
+    }
+
+    public static interface Index {        
+        public FieldIndex getFieldIndex(int index);
+        
+        public int hashCodeOf(ReteTuple tuple);
+
+        public int hashCodeOf(Object object);
+
+        public boolean equal(Object object,
+                             ReteTuple tuple);
+
+        public boolean equal(ReteTuple tuple1,
+                             ReteTuple tuple2);
+
+        public boolean equal(Object object1,
+                             Object object2);
+    }
+
+    public static class SingleIndex
+        implements
+        Index {
+
+        private FieldExtractor extractor;
+        private Declaration    declaration;
+        private Evaluator      evaluator;
+
+        private int            startResult;
+
+        public SingleIndex(final FieldIndex[] indexes,
+                           final int startResult) {
+            this.startResult = startResult;
+
+            this.extractor = indexes[0].extractor;
+            this.declaration = indexes[0].declaration;
+            this.evaluator = indexes[0].evaluator;
+        }
+
+        public FieldIndex getFieldIndex(int index) {
+            if ( index > 0 ) {
+                throw new IllegalArgumentException("Index position " + index + " does not exist" );
+            }
+            return new FieldIndex(extractor, declaration, evaluator);
+        }
+        
+        
+        public int hashCodeOf(final Object object) {
+            int hashCode = this.startResult;
+            hashCode = TupleIndexHashTable.PRIME * hashCode + this.extractor.getHashCode( null, object );
+            return rehash( hashCode );
+        }
+
+        public int hashCodeOf(final ReteTuple tuple) {
+            int hashCode = this.startResult;
+            hashCode = TupleIndexHashTable.PRIME * hashCode + this.declaration.getHashCode( null, tuple.get( this.declaration ).getObject() );
+            return rehash( hashCode );
+        }
+
+        public boolean equal(final Object right,
+                             final ReteTuple tuple) {
+            final Object left = tuple.get( this.declaration ).getObject();
+
+            return this.evaluator.evaluate( null,
+                                            this.declaration.getExtractor(),
+                                            left,
+                                            this.extractor, right );
+        }
+
+        public boolean equal(final Object object1,
+                             final Object object2) {
+
+            return this.evaluator.evaluate( null,
+                                            this.extractor,
+                                            object1,
+                                            this.extractor, object2 );
+        }
+
+        public boolean equal(final ReteTuple tuple1,
+                             final ReteTuple tuple2) {
+            final Object object1 = tuple1.get( this.declaration ).getObject();
+            final Object object2 = tuple2.get( this.declaration ).getObject();
+            return this.evaluator.evaluate( null,
+                                            this.declaration.getExtractor(),
+                                            object1,
+                                            this.declaration.getExtractor(), object2 );
+        }
+
+        public int rehash(int h) {
+            h += ~(h << 9);
+            h ^= (h >>> 14);
+            h += (h << 4);
+            h ^= (h >>> 10);
+            return h;
+        }
+
+    }
+
+    public static class DoubleCompositeIndex
+        implements
+        Index {
+        private FieldIndex index0;
+        private FieldIndex index1;
+
+        private int        startResult;
+
+        public DoubleCompositeIndex(final FieldIndex[] indexes,
+                                    final int startResult) {
+            this.startResult = startResult;
+
+            this.index0 = indexes[0];
+            this.index1 = indexes[1];
+        }
+        
+        public FieldIndex getFieldIndex(int index) {
+            switch ( index ) {
+                case 0:
+                    return index0;
+                case 1:
+                    return index1;
+                default:
+                    throw new IllegalArgumentException("Index position " + index + " does not exist" );
+            }
+        }
+
+        public int hashCodeOf(final Object object) {
+            int hashCode = this.startResult;
+
+            hashCode = TupleIndexHashTable.PRIME * hashCode + this.index0.extractor.getHashCode( null, object );
+            hashCode = TupleIndexHashTable.PRIME * hashCode + this.index1.extractor.getHashCode( null, object );
+
+            return rehash( hashCode );
+        }
+
+        public int hashCodeOf(final ReteTuple tuple) {
+            int hashCode = this.startResult;
+
+            hashCode = TupleIndexHashTable.PRIME * hashCode + this.index0.declaration.getHashCode( null, tuple.get( this.index0.declaration ).getObject() );
+            hashCode = TupleIndexHashTable.PRIME * hashCode + this.index1.declaration.getHashCode( null, tuple.get( this.index1.declaration ).getObject() );
+
+            return rehash( hashCode );
+        }
+
+        public boolean equal(final Object right,
+                             final ReteTuple tuple) {
+            final Object left1 = tuple.get( this.index0.declaration ).getObject();
+            final Object left2 = tuple.get( this.index1.declaration ).getObject();
+
+            return this.index0.evaluator.evaluate( null,
+                                                   this.index0.declaration.getExtractor(),
+                                                   left1,
+                                                   this.index0.extractor, right ) && this.index1.evaluator.evaluate( null,
+                                                                                              this.index1.declaration.getExtractor(),
+                                                                                              left2,
+                                                                                              this.index1.extractor, right );
+        }
+
+        public boolean equal(final ReteTuple tuple1,
+                             final ReteTuple tuple2) {
+            final Object object11 = tuple1.get( this.index0.declaration ).getObject();
+            final Object object12 = tuple2.get( this.index0.declaration ).getObject();
+
+            final Object object21 = tuple1.get( this.index1.declaration ).getObject();
+            final Object object22 = tuple2.get( this.index1.declaration ).getObject();
+
+            return this.index0.evaluator.evaluate( null,
+                                                   this.index0.declaration.getExtractor(),
+                                                   object11,
+                                                   this.index0.declaration.getExtractor(), object12 ) && this.index1.evaluator.evaluate( null,
+                                                                                                 this.index1.declaration.getExtractor(),
+                                                                                                 object21,
+                                                                                                 this.index1.declaration.getExtractor(), object22 );
+        }
+
+        public boolean equal(final Object object1,
+                             final Object object2) {
+            return this.index0.evaluator.evaluate( null,
+                                                   this.index0.extractor,
+                                                   object1,
+                                                   this.index0.extractor, object2 ) && this.index1.evaluator.evaluate( null,
+                                                                                                this.index1.extractor,
+                                                                                                object1,
+                                                                                                this.index1.extractor, object2 );
+        }
+
+        public int rehash(int h) {
+            h += ~(h << 9);
+            h ^= (h >>> 14);
+            h += (h << 4);
+            h ^= (h >>> 10);
+            return h;
+        }
+    }
+
+    public static class TripleCompositeIndex
+        implements
+        Index {
+        private FieldIndex index0;
+        private FieldIndex index1;
+        private FieldIndex index2;
+
+        private int        startResult;
+
+        public TripleCompositeIndex(final FieldIndex[] indexes,
+                                    final int startResult) {
+            this.startResult = startResult;
+
+            this.index0 = indexes[0];
+            this.index1 = indexes[1];
+            this.index2 = indexes[2];
+        }
+        
+        public FieldIndex getFieldIndex(int index) {
+            switch ( index ) {
+                case 0:
+                    return index0;
+                case 1:
+                    return index1;
+                case 2:
+                    return index2;                    
+                default:
+                    throw new IllegalArgumentException("Index position " + index + " does not exist" );
+            }
+        }        
+
+        public int hashCodeOf(final Object object) {
+            int hashCode = this.startResult;
+
+            hashCode = TupleIndexHashTable.PRIME * hashCode + this.index0.extractor.getHashCode( null, object );;
+            hashCode = TupleIndexHashTable.PRIME * hashCode + this.index1.extractor.getHashCode( null, object );;
+            hashCode = TupleIndexHashTable.PRIME * hashCode + this.index2.extractor.getHashCode( null, object );;
+
+            return rehash( hashCode );
+        }
+
+        public int hashCodeOf(final ReteTuple tuple) {
+            int hashCode = this.startResult;
+
+            hashCode = TupleIndexHashTable.PRIME * hashCode + this.index0.declaration.getHashCode( null, tuple.get( this.index0.declaration ).getObject() );
+            hashCode = TupleIndexHashTable.PRIME * hashCode + this.index1.declaration.getHashCode( null, tuple.get( this.index1.declaration ).getObject() );
+            hashCode = TupleIndexHashTable.PRIME * hashCode + this.index2.declaration.getHashCode( null, tuple.get( this.index2.declaration ).getObject() );
+
+            return rehash( hashCode );
+        }
+
+        public boolean equal(final Object right,
+                             final ReteTuple tuple) {
+            final Object left1 = tuple.get( this.index0.declaration ).getObject();
+            final Object left2 = tuple.get( this.index1.declaration ).getObject();
+            final Object left3 = tuple.get( this.index2.declaration ).getObject();
+
+            return this.index0.evaluator.evaluate( null,
+                                                   this.index0.declaration.getExtractor(),
+                                                   left1,
+                                                   this.index0.extractor, right ) && this.index1.evaluator.evaluate( null,
+                                                                                              this.index1.declaration.getExtractor(),
+                                                                                              left2,
+                                                                                              this.index1.extractor, right ) && this.index2.evaluator.evaluate( null,
+                                                                                                                                         this.index2.declaration.getExtractor(),
+                                                                                                                                         left3,
+                                                                                                                                         this.index2.extractor, right );
+        }
+
+        public boolean equal(final ReteTuple tuple1,
+                             final ReteTuple tuple2) {
+            final Object object11 = tuple1.get( this.index0.declaration ).getObject();
+            final Object object12 = tuple2.get( this.index0.declaration ).getObject();
+            final Object object21 = tuple1.get( this.index1.declaration ).getObject();
+            final Object object22 = tuple2.get( this.index1.declaration ).getObject();
+            final Object object31 = tuple1.get( this.index2.declaration ).getObject();
+            final Object object32 = tuple2.get( this.index2.declaration ).getObject();
+
+            return this.index0.evaluator.evaluate( null,
+                                                   this.index0.declaration.getExtractor(),
+                                                   object11,
+                                                   this.index0.declaration.getExtractor(), object12 ) && this.index1.evaluator.evaluate( null,
+                                                                                                 this.index1.declaration.getExtractor(),
+                                                                                                 object21,
+                                                                                                 this.index1.declaration.getExtractor(), object22 ) && this.index2.evaluator.evaluate( null,
+                                                                                                                                               this.index2.declaration.getExtractor(),
+                                                                                                                                               object31,
+                                                                                                                                               this.index2.declaration.getExtractor(), object32 );
+        }
+
+        public boolean equal(final Object object1,
+                             final Object object2) {
+            return this.index0.evaluator.evaluate( null,
+                                                   this.index0.extractor,
+                                                   object1,
+                                                   this.index0.extractor, object2 ) && this.index1.evaluator.evaluate( null,
+                                                                                                this.index1.extractor,
+                                                                                                object1,
+                                                                                                this.index1.extractor, object2 ) && this.index2.evaluator.evaluate( null,
+                                                                                                                                             this.index2.extractor,
+                                                                                                                                             object1,
+                                                                                                                                             this.index2.extractor, object2 );
+        }
+
+        public int rehash(int h) {
+            h += ~(h << 9);
+            h ^= (h >>> 14);
+            h += (h << 4);
+            h ^= (h >>> 10);
+            return h;
+        }
+
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ArrayUtils.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ArrayUtils.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ArrayUtils.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,237 @@
+package org.drools.util;
+
+import java.lang.reflect.Array;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+/**
+ * Taken from commons lang
+ * 
+ * <p>Operations on arrays, primitive arrays (like <code>int[]</code>) and
+ * primitive wrapper arrays (like <code>Integer[]</code>).</p>
+ * 
+ * <p>This class tries to handle <code>null</code> input gracefully.
+ * An exception will not be thrown for a <code>null</code>
+ * array input. However, an Object array that contains a <code>null</code>
+ * element may throw an exception. Each method documents its behaviour.</p>
+ *
+ * @author Stephen Colebourne
+ * @author Moritz Petersen
+ * @author <a href="mailto:fredrik at westermarck.com">Fredrik Westermarck</a>
+ * @author Nikolay Metchev
+ * @author Matthew Hawthorne
+ * @author Tim O'Brien
+ * @author Pete Gieser
+ * @author Gary Gregory
+ * @author <a href="mailto:equinus100 at hotmail.com">Ashwin S</a>
+ * @author Maarten Coene
+ * @since 2.0
+ * @version $Id$
+ */
+public class ArrayUtils {
+    // Taken from commons ArrayUtils
+
+    public static final int INDEX_NOT_FOUND = -1;
+
+    /**
+     * <p>Checks if the object is in the given array.</p>
+     *
+     * <p>The method returns <code>false</code> if a <code>null</code> array is passed in.</p>
+     * 
+     * @param array  the array to search through
+     * @param objectToFind  the object to find
+     * @return <code>true</code> if the array contains the object
+     */
+    public static boolean contains(Object[] array,
+                                   Object objectToFind) {
+        return indexOf( array,
+                        objectToFind ) != INDEX_NOT_FOUND;
+    }
+
+    // IndexOf search
+    // ----------------------------------------------------------------------
+
+    // Object IndexOf
+    //-----------------------------------------------------------------------
+    /**
+     * <p>Finds the index of the given object in the array.</p>
+     *
+     * <p>This method returns {@link #INDEX_NOT_FOUND} (<code>-1</code>) for a <code>null</code> input array.</p>
+     * 
+     * @param array  the array to search through for the object, may be <code>null</code>
+     * @param objectToFind  the object to find, may be <code>null</code>
+     * @return the index of the object within the array, 
+     *  {@link #INDEX_NOT_FOUND} (<code>-1</code>) if not found or <code>null</code> array input
+     */
+    public static int indexOf(Object[] array,
+                              Object objectToFind) {
+        return indexOf( array,
+                        objectToFind,
+                        0 );
+    }
+
+    /**
+     * <p>Finds the index of the given object in the array starting at the given index.</p>
+     *
+     * <p>This method returns {@link #INDEX_NOT_FOUND} (<code>-1</code>) for a <code>null</code> input array.</p>
+     *
+     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
+     * length will return {@link #INDEX_NOT_FOUND} (<code>-1</code>).</p>
+     * 
+     * @param array  the array to search through for the object, may be <code>null</code>
+     * @param objectToFind  the object to find, may be <code>null</code>
+     * @param startIndex  the index to start searching at
+     * @return the index of the object within the array starting at the index,
+     *  {@link #INDEX_NOT_FOUND} (<code>-1</code>) if not found or <code>null</code> array input
+     */
+    public static int indexOf(Object[] array,
+                              Object objectToFind,
+                              int startIndex) {
+        if ( array == null ) {
+            return INDEX_NOT_FOUND;
+        }
+        if ( startIndex < 0 ) {
+            startIndex = 0;
+        }
+        if ( objectToFind == null ) {
+            for ( int i = startIndex; i < array.length; i++ ) {
+                if ( array[i] == null ) {
+                    return i;
+                }
+            }
+        } else {
+            for ( int i = startIndex; i < array.length; i++ ) {
+                if ( objectToFind.equals( array[i] ) ) {
+                    return i;
+                }
+            }
+        }
+        return INDEX_NOT_FOUND;
+    }
+
+    public static int hashCode(Object[] array) {
+        final int PRIME = 31;
+        if ( array == null ) return 0;
+        int result = 1;
+        for ( int index = 0; index < array.length; index++ ) {
+            result = PRIME * result + (array[index] == null ? 0 : array[index].hashCode());
+        }
+        return result;
+    }
+
+    public static Object[] copyOf(Object[] original,
+                                  int newLength,
+                                  Class newType) {
+        Object[] arr = (newType == Object[].class) ? new Object[newLength] : (Object[]) Array.newInstance( newType.getComponentType(),
+                                                                                                           newLength );
+        int len = (original.length < newLength ? original.length : newLength);
+        System.arraycopy( original,
+                          0,
+                          arr,
+                          0,
+                          len );
+        return arr;
+    }
+
+    /**
+     * @since 1.5
+     */
+    public static boolean deepEquals(Object[] a1,
+                                     Object[] a2) {
+        if ( a1 == a2 ) return true;
+        if ( a1 == null || a2 == null ) return false;
+        int len = a1.length;
+        if ( len != a2.length ) return false;
+        for ( int i = 0; i < len; i++ ) {
+            Object e1 = a1[i];
+            Object e2 = a2[i];
+            if ( e1 == e2 ) continue;
+            if ( e1 == null ) return false;
+            boolean eq = (e1.getClass() != e2.getClass() || !e1.getClass().isArray()  || !e2.getClass().isArray() ) ? e1.equals( e2 ) : (e1 instanceof Object[] && e2 instanceof Object[]) ? deepEquals( (Object[]) e1,
+                                                                                                                                                                          (Object[]) e2 ) : (e1 instanceof byte[] && e2 instanceof byte[]) ? equals( (byte[]) e1,
+                                                                                                                                                                                                                                                     (byte[]) e2 ) : (e1 instanceof short[] && e2 instanceof short[]) ? equals( (short[]) e1,
+                                                                                                                                                                                                                                                                                                                                (short[]) e2 ) : (e1 instanceof int[] && e2 instanceof int[]) ? equals( (int[]) e1,
+                                                                                                                                                                                                                                                                                                                                                                                                        (int[]) e2 ) : (e1 instanceof long[] && e2 instanceof long[]) ? equals( (long[]) e1,
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                (long[]) e2 ) : (e1 instanceof char[] && e2 instanceof char[]) ? equals( (char[]) e1,
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         (char[]) e2 ) : (e1 instanceof boolean[] && e2 instanceof boolean[]) ? equals( (boolean[]) e1,
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (boolean[]) e2 ) : (e1 instanceof float[] && e2 instanceof float[]) ? equals( (float[]) e1,
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      (float[]) e2 ) : (e1 instanceof double[] && e2 instanceof double[]) ? equals( (double[]) e1,
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (double[]) e2 ) : e1.equals( e2 );
+
+            if ( !eq ) return false;
+        }
+        return true;
+    }
+
+    // Equality Testing
+
+    public static boolean equals(long[] a,
+                                 long[] a2) {
+        return java.util.Arrays.equals( a,
+                                        a2 );
+    }
+
+    public static boolean equals(int[] a,
+                                 int[] a2) {
+        return java.util.Arrays.equals( a,
+                                        a2 );
+    }
+
+    public static boolean equals(short[] a,
+                                 short a2[]) {
+        return java.util.Arrays.equals( a,
+                                        a2 );
+    }
+
+    public static boolean equals(char[] a,
+                                 char[] a2) {
+        return java.util.Arrays.equals( a,
+                                        a2 );
+    }
+
+    public static boolean equals(byte[] a,
+                                 byte[] a2) {
+        return java.util.Arrays.equals( a,
+                                        a2 );
+    }
+
+    public static boolean equals(boolean[] a,
+                                 boolean[] a2) {
+        return java.util.Arrays.equals( a,
+                                        a2 );
+    }
+
+    public static boolean equals(double[] a,
+                                 double[] a2) {
+        return java.util.Arrays.equals( a,
+                                        a2 );
+    }
+
+    public static boolean equals(float[] a,
+                                 float[] a2) {
+        return java.util.Arrays.equals( a,
+                                        a2 );
+    }
+
+    public static boolean equals(Object[] a,
+                                 Object[] a2) {
+        return java.util.Arrays.equals( a,
+                                        a2 );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/BinaryHeapQueue.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/BinaryHeapQueue.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/BinaryHeapQueue.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,324 @@
+package org.drools.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.Comparator;
+import java.util.NoSuchElementException;
+
+public class BinaryHeapQueue
+    implements
+    Queue,
+    Serializable {
+    /** The default capacity for a binary heap. */
+    private final static int DEFAULT_CAPACITY = 13;
+
+    /** The comparator used to order the elements */
+    private final Comparator comparator;
+
+    /** The number of elements currently in this heap. */
+    private int              size;
+
+    /** The elements in this heap. */
+    private Queueable[]      elements;
+
+    /**
+     * Constructs a new <code>BinaryHeap</code> that will use the given
+     * comparator to order its elements.
+     *
+     * @param comparator the comparator used to order the elements, null
+     *                   means use natural order
+     */
+    public BinaryHeapQueue(final Comparator comparator) {
+        this( comparator,
+              BinaryHeapQueue.DEFAULT_CAPACITY );
+    }
+
+    /**
+     * Constructs a new <code>BinaryHeap</code>.
+     *
+     * @param comparator the comparator used to order the elements, null
+     *                   means use natural order
+     * @param capacity   the initial capacity for the heap
+     * @throws IllegalArgumentException if <code>capacity</code> is &lt;= <code>0</code>
+     */
+    public BinaryHeapQueue(final Comparator comparator,
+                           final int capacity) {
+        if ( capacity <= 0 ) {
+            throw new IllegalArgumentException( "invalid capacity" );
+        }
+
+        //+1 as 0 is noop
+        this.elements = new Queueable[capacity + 1];
+        this.comparator = comparator;
+    }
+
+    //-----------------------------------------------------------------------
+
+    /**
+     * Clears all elements from queue.
+     */
+    public void clear() {
+        this.elements = new Queueable[this.elements.length]; // for gc
+        this.size = 0;
+    }
+
+    /**
+     * Tests if queue is empty.
+     *
+     * @return <code>true</code> if queue is empty; <code>false</code>
+     *         otherwise.
+     */
+    public boolean isEmpty() {
+        return this.size == 0;
+    }
+
+    /**
+     * Tests if queue is full.
+     *
+     * @return <code>true</code> if queue is full; <code>false</code>
+     *         otherwise.
+     */
+    public boolean isFull() {
+        //+1 as Queueable 0 is noop
+        return this.elements.length == this.size + 1;
+    }
+
+    /**
+     * Returns the number of elements in this heap.
+     *
+     * @return the number of elements in this heap
+     */
+    public int size() {
+        return this.size;
+    }
+
+    /**
+     * Inserts an Queueable into queue.
+     *
+     * @param element the Queueable to be inserted
+     */
+    public void enqueue(final Queueable element) {
+        if ( isFull() ) {
+            grow();
+        }
+
+        percolateUpMinHeap( element );
+    }
+
+    /**
+     * Returns the Queueable on top of heap and remove it.
+     *
+     * @return the Queueable at top of heap
+     * @throws NoSuchElementException if <code>isEmpty() == true</code>
+     */
+    public Queueable dequeue() throws NoSuchElementException {
+        if ( isEmpty() ) {
+            return null;
+        }
+
+        final Queueable result = this.elements[1];
+        result.dequeue();
+
+        // Code bellow was removed because it is already executed
+        // inside result.dequeue()
+        //
+        //        setElement(1, this.elements[this.size--]);
+        //        this.elements[this.size + 1] = null;
+        //
+        //        if (this.size != 0) {
+        //            percolateDownMinHeap(1);
+        //        }
+
+        return result;
+    }
+
+    /**
+     *
+     * @param index
+     */
+    public Queueable dequeue(final int index) {
+        if ( index < 1 || index > this.size ) {
+            //throw new NoSuchElementException();
+            return null;
+        }
+
+        final Queueable result = this.elements[index];
+        setElement( index,
+                    this.elements[this.size] );
+        this.elements[this.size] = null;
+        this.size--;
+        if ( this.size != 0 && index <= this.size ) {
+            int compareToParent = 0;
+            if ( index > 1 ) {
+                compareToParent = compare( this.elements[index],
+                                           this.elements[index / 2] );
+            }
+            if ( index > 1 && compareToParent < 0 ) {
+                percolateUpMinHeap( index );
+            } else {
+                percolateDownMinHeap( index );
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Percolates Queueable down heap from the position given by the index.
+     * <p/>
+     * Assumes it is a minimum heap.
+     *
+     * @param index the index for the Queueable
+     */
+    private void percolateDownMinHeap(final int index) {
+        final Queueable element = this.elements[index];
+        int hole = index;
+
+        while ( (hole * 2) <= this.size ) {
+            int child = hole * 2;
+
+            // if we have a right child and that child can not be percolated
+            // up then move onto other child
+            if ( child != this.size && compare( this.elements[child + 1],
+                                                this.elements[child] ) < 0 ) {
+                child++;
+            }
+
+            // if we found resting place of bubble then terminate search
+            if ( compare( this.elements[child],
+                          element ) >= 0 ) {
+                break;
+            }
+
+            setElement( hole,
+                        this.elements[child] );
+            hole = child;
+        }
+
+        setElement( hole,
+                    element );
+    }
+
+    /**
+     * Percolates Queueable up heap from the position given by the index.
+     * <p/>
+     * Assumes it is a minimum heap.
+     *
+     * @param index the index of the Queueable to be percolated up
+     */
+    private void percolateUpMinHeap(final int index) {
+        int hole = index;
+        final Queueable element = this.elements[hole];
+        while ( hole > 1 && compare( element,
+                                     this.elements[hole / 2] ) < 0 ) {
+            // save Queueable that is being pushed down
+            // as the Queueable "bubble" is percolated up
+            final int next = hole / 2;
+            setElement( hole,
+                        this.elements[next] );
+            hole = next;
+        }
+        setElement( hole,
+                    element );
+    }
+
+    /**
+     * Percolates a new Queueable up heap from the bottom.
+     * <p/>
+     * Assumes it is a minimum heap.
+     *
+     * @param element the Queueable
+     */
+    private void percolateUpMinHeap(final Queueable element) {
+        setElement( ++this.size,
+                    element );
+        percolateUpMinHeap( this.size );
+    }
+
+    /**
+     * Compares two objects using the comparator if specified, or the
+     * natural order otherwise.
+     *
+     * @param a the first object
+     * @param b the second object
+     * @return -ve if a less than b, 0 if they are equal, +ve if a greater than b
+     */
+    private int compare(final Queueable a,
+                        final Queueable b) {
+        return this.comparator.compare( a,
+                                        b );
+    }
+
+    /**
+     * Increases the size of the heap to support additional elements
+     */
+    private void grow() {
+        final Queueable[] elements = new Queueable[this.elements.length * 2];
+        System.arraycopy( this.elements,
+                          0,
+                          elements,
+                          0,
+                          this.elements.length );
+        this.elements = elements;
+    }
+
+    /**
+     *
+     * @param index
+     * @param element
+     */
+    private void setElement(final int index,
+                            final Queueable element) {
+        this.elements[index] = element;
+        element.enqueued( this,
+                          index );
+    }
+
+    public Queueable[] getQueueable() {
+        return this.elements;
+    }
+
+    public Object[] toArray() {
+        final Object[] result = new Object[this.size];
+        System.arraycopy( this.elements,
+                          1,
+                          result,
+                          0,
+                          this.size );
+        return result;
+    }
+
+    public Object[] toArray(Object a[]) {
+        if ( a.length < this.size ) {
+            a = (Object[]) java.lang.reflect.Array.newInstance( a.getClass().getComponentType(),
+                                                                this.size );
+        }
+
+        System.arraycopy( this.elements,
+                          1,
+                          a,
+                          0,
+                          this.size );
+
+        if ( a.length > this.size ) {
+            a[this.size] = null;
+        }
+
+        return a;
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/BinaryRuleBaseLoader.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/BinaryRuleBaseLoader.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/BinaryRuleBaseLoader.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,117 @@
+package org.drools.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.RuntimeDroolsException;
+import org.drools.common.DroolsObjectInputStream;
+import org.drools.rule.Package;
+
+/**
+ * This loads up rulebases from binary packages.
+ * Can work with an existing or a new rulebase.
+ * This is useful for deployment.
+ * 
+ * @author Michael Neale
+ */
+public class BinaryRuleBaseLoader {
+
+    private RuleBase    ruleBase;
+    private ClassLoader classLoader;
+
+    /**
+     * This will create a new default rulebase (which is initially empty).
+     * Optional parent classLoader for the Package's internal ClassLoader
+     * is Thread.currentThread.getContextClassLoader()
+     */
+    public BinaryRuleBaseLoader() {
+        this( RuleBaseFactory.newRuleBase(), null );
+    }    
+
+    /**
+     * This will add any binary packages to the rulebase.
+     * Optional parent classLoader for the Package's internal ClassLoader
+     * is Thread.currentThread.getContextClassLoader()
+     */
+    public BinaryRuleBaseLoader(RuleBase rb) {
+        this( rb, null);
+    }
+
+    /**
+     * This will add any binary packages to the rulebase.
+     * Optional classLoader to be used as the parent ClassLoader
+     * for the Package's internal ClassLoader, is Thread.currentThread.getContextClassLoader()
+     * if not user specified.
+     */
+    public BinaryRuleBaseLoader(RuleBase rb, ClassLoader classLoader) {
+        if ( classLoader == null ) {
+            classLoader = Thread.currentThread().getContextClassLoader();
+            if ( classLoader == null ) {
+                classLoader = this.getClass().getClassLoader();
+            }
+        }        
+        this.ruleBase = rb;
+        this.classLoader = classLoader;
+    }
+    
+    /**
+     * This will add the BINARY package to the rulebase.
+     * Uses the member ClassLoader as the Package's internal parent classLoader
+     * which is Thread.currentThread.getContextClassLoader if not user specified
+     * @param in An input stream to the serialized package.
+     */    
+    public void addPackage(InputStream in) {
+        addPackage(in, this.classLoader);
+    }
+
+    /**
+     * This will add the BINARY package to the rulebase.
+     * @param in An input stream to the serialized package.
+     * @param optional classLoader used as the parent ClassLoader for the Package's internal ClassLaoder  
+     */    
+    public void addPackage(InputStream in, ClassLoader classLoader) {
+        if ( classLoader == null ) {
+            classLoader = this.classLoader;
+        }
+        
+        try {
+            ObjectInputStream oin = new DroolsObjectInputStream( in, classLoader);
+            Object opkg = oin.readObject();
+            if ( !(opkg instanceof Package) ) {
+                throw new IllegalArgumentException( "Can only add instances of org.drools.rule.Package to a rulebase instance." );
+            }
+            Package binPkg = (Package) opkg;
+
+            if ( !binPkg.isValid() ) {
+                throw new IllegalArgumentException( "Can't add a non valid package to a rulebase." );
+            }
+
+            try {
+                this.ruleBase.addPackage( binPkg );
+            } catch ( Exception e ) {
+                throw new RuntimeDroolsException( "Unable to add package to the rulebase.",
+                                                  e );
+            }
+
+        } catch ( IOException e ) {
+            throw new RuntimeDroolsException( e );
+        } catch ( ClassNotFoundException e ) {
+            throw new RuntimeDroolsException( e );
+        } finally {
+            try {
+                in.close();
+            } catch ( IOException e ) {
+                throw new RuntimeException( e );
+            }
+        }
+
+    }
+
+    public RuleBase getRuleBase() {
+        return this.ruleBase;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ChainedProperties.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ChainedProperties.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ChainedProperties.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,251 @@
+/**
+ * 
+ */
+package org.drools.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Serializable;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+public class ChainedProperties
+    implements
+    Serializable {
+    private final List props;
+    private final List defaultProps;
+
+    public ChainedProperties(String confFileName) {
+        this( null,
+              confFileName );
+    }
+
+    public ChainedProperties(ClassLoader classLoader,
+                             String confFileName) {
+        this( classLoader,
+              confFileName,
+              true );
+    }
+
+    public ChainedProperties(ClassLoader classLoader,
+                             String confFileName,
+                             boolean populateDefaults) {
+        if ( classLoader == null ) {
+            classLoader = Thread.currentThread().getContextClassLoader();
+            if ( classLoader == null ) {
+                classLoader = this.getClass().getClassLoader();
+            }
+        }
+
+        this.props = new ArrayList();
+        this.defaultProps = new ArrayList();
+
+        // Properties added in precedence order
+
+        // System defined properties always get precedence
+        addProperties( System.getProperties() );
+
+        // System property defined properties file
+        loadProperties( System.getProperty( "drools." + confFileName ),
+                        this.props );
+
+        // User home properties file
+        loadProperties( System.getProperty( "user.home" ) + "/drools." + confFileName,
+                        this.props );
+
+        // Working directory properties file
+        loadProperties( "drools." + confFileName,
+                        this.props );
+
+        // check META-INF directories for all known ClassLoaders
+        ClassLoader confClassLoader = classLoader;
+        if ( confClassLoader != null ) {
+            loadProperties( getResources( "META-INF/drools." + confFileName,
+                                          confClassLoader ),
+                            this.props );
+        }
+
+        confClassLoader = getClass().getClassLoader();
+        if ( confClassLoader != null && confClassLoader != classLoader ) {
+            loadProperties( getResources( "META-INF/drools." + confFileName,
+                                          confClassLoader ),
+                            this.props );
+        }
+
+        confClassLoader = Thread.currentThread().getContextClassLoader();
+        if ( confClassLoader != null && confClassLoader != classLoader ) {
+            loadProperties( getResources( "META-INF/drools." + confFileName,
+                                          confClassLoader ),
+                            this.props );
+        }
+
+        confClassLoader = ClassLoader.getSystemClassLoader();
+        if ( confClassLoader != null && confClassLoader != classLoader ) {
+            loadProperties( getResources( "META-INF/drools." + confFileName,
+                                          confClassLoader ),
+                            this.props );
+        }
+
+        if ( !populateDefaults ) {
+            return;
+        }
+
+        // load defaults
+        confClassLoader = classLoader;
+        if ( confClassLoader != null ) {
+            loadProperties( getResources( "META-INF/drools.default." + confFileName,
+                                          confClassLoader ),
+                            this.defaultProps );
+        }
+
+        confClassLoader = getClass().getClassLoader();
+        if ( confClassLoader != null && confClassLoader != classLoader ) {
+            loadProperties( getResources( "META-INF/drools.default." + confFileName,
+                                          confClassLoader ),
+                            this.defaultProps );
+        }
+
+        confClassLoader = Thread.currentThread().getContextClassLoader();
+        if ( confClassLoader != null && confClassLoader != classLoader ) {
+            loadProperties( getResources( "META-INF/drools.default." + confFileName,
+                                          confClassLoader ),
+                            this.defaultProps );
+        }
+
+        confClassLoader = ClassLoader.getSystemClassLoader();
+        if ( confClassLoader != null && confClassLoader != classLoader ) {
+            loadProperties( getResources( "META-INF/drools.default." + confFileName,
+                                          confClassLoader ),
+                            this.defaultProps );
+        }
+    }
+
+    private Enumeration getResources(String name,
+                                     ClassLoader classLoader) {
+        Enumeration enumeration = null;
+        try {
+            enumeration = classLoader.getResources( name );
+        } catch ( IOException e ) {
+            e.printStackTrace();
+        }
+        return enumeration;
+    }
+
+    public void addProperties(Properties properties) {
+        this.props.add( properties );
+    }
+
+    public String getProperty(String key,
+                              String defaultValue) {
+        String value = null;
+        for ( Iterator it = this.props.iterator(); it.hasNext(); ) {
+            Properties props = (Properties) it.next();
+            value = props.getProperty( key );
+            if ( value != null ) {
+                break;
+            }
+        }
+        if ( value == null ) {
+            for ( Iterator it = this.defaultProps.iterator(); it.hasNext(); ) {
+                Properties props = (Properties) it.next();
+                value = props.getProperty( key );
+                if ( value != null ) {
+                    break;
+                }
+            }
+        }
+        return (value != null) ? value : defaultValue;
+    }
+
+    public void mapStartsWith(Map map,
+                              String startsWith,
+                              boolean includeSubProperties) {
+        for ( Iterator it = this.props.iterator(); it.hasNext(); ) {
+            Properties props = (Properties) it.next();
+            mapStartsWith( map,
+                           props,
+                           startsWith,
+                           includeSubProperties );
+        }
+
+        for ( Iterator it = this.defaultProps.iterator(); it.hasNext(); ) {
+            Properties props = (Properties) it.next();
+            mapStartsWith( map,
+                           props,
+                           startsWith,
+                           includeSubProperties );
+        }
+    }
+
+    private void mapStartsWith(Map map,
+                               Properties properties,
+                               String startsWith,
+                               boolean includeSubProperties) {
+        Enumeration enumeration = properties.propertyNames();
+        while ( enumeration.hasMoreElements() ) {
+            String key = (String) enumeration.nextElement();
+            if ( key.startsWith( startsWith ) ) {
+                if ( !includeSubProperties && key.substring( startsWith.length() + 1 ).indexOf( '.' ) > 0 ) {
+                    // +1 to the length, as we do allow the direct property, just not ones below it
+                    // This key has sub properties beyond the given startsWith, so skip
+                    continue;
+                }
+                if ( !map.containsKey( key ) ) {
+                    map.put( key,
+                             properties.getProperty( key ) );
+                }
+
+            }
+        }
+    }
+
+    private void loadProperties(Enumeration enumeration,
+                                List chain) {
+        if ( enumeration == null ) {
+            return;
+        }
+
+        while ( enumeration.hasMoreElements() ) {
+            URL url = (URL) enumeration.nextElement();
+            loadProperties( url,
+                            chain );
+        }
+    }
+
+    private void loadProperties(String fileName,
+                                List chain) {
+        if ( fileName != null ) {
+            File file = new File( fileName );
+            if ( file != null && file.exists() ) {
+                try {
+                    loadProperties( file.toURL(),
+                                    chain );
+                } catch ( MalformedURLException e ) {
+                    throw new IllegalArgumentException( "file.toURL() failed for drools.packagebuilder.conf properties value '" + file + "'" );
+                }
+            } else {
+                //throw new IllegalArgumentException( "drools.packagebuilder.conf is specified but cannot be found '" + file + "'" );
+            }
+        }
+    }
+
+    private void loadProperties(URL confURL,
+                                List chain) {
+        if ( confURL == null ) {
+            return;
+        }
+        Properties properties = new Properties();
+        try {
+            properties.load( confURL.openStream() );
+            chain.add( properties );
+        } catch ( IOException e ) {
+            //throw new IllegalArgumentException( "Invalid URL to properties file '" + confURL.toExternalForm() + "'" );
+        }
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ClassUtils.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ClassUtils.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ClassUtils.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,155 @@
+package org.drools.util;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public final class ClassUtils {
+    private static Map classes = Collections.synchronizedMap( new HashMap() );
+
+    /**
+     * Please do not use - internal
+     * org/my/Class.xxx -> org.my.Class
+     */
+    public static String convertResourceToClassName(final String pResourceName) {
+        return ClassUtils.stripExtension( pResourceName ).replace( '/',
+                                                                   '.' );
+    }
+
+    /**
+     * Please do not use - internal
+     * org.my.Class -> org/my/Class.class
+     */
+    public static String convertClassToResourcePath(final String pName) {
+        return pName.replace( '.',
+                              '/' ) + ".class";
+    }
+
+    /**
+     * Please do not use - internal
+     * org/my/Class.xxx -> org/my/Class
+     */
+    public static String stripExtension(final String pResourceName) {
+        final int i = pResourceName.lastIndexOf( '.' );
+        final String withoutExtension = pResourceName.substring( 0,
+                                                                 i );
+        return withoutExtension;
+    }
+
+    public static String toJavaCasing(final String pName) {
+        final char[] name = pName.toLowerCase().toCharArray();
+        name[0] = Character.toUpperCase( name[0] );
+        return new String( name );
+    }
+
+    public static String clazzName(final File base,
+                                   final File file) {
+        final int rootLength = base.getAbsolutePath().length();
+        final String absFileName = file.getAbsolutePath();
+        final int p = absFileName.lastIndexOf( '.' );
+        final String relFileName = absFileName.substring( rootLength + 1,
+                                                          p );
+        final String clazzName = relFileName.replace( File.separatorChar,
+                                                      '.' );
+        return clazzName;
+    }
+
+    public static String relative(final File base,
+                                  final File file) {
+        final int rootLength = base.getAbsolutePath().length();
+        final String absFileName = file.getAbsolutePath();
+        final String relFileName = absFileName.substring( rootLength + 1 );
+        return relFileName;
+    }
+
+    public static String canonicalName(Class clazz) {
+        StringBuffer name = new StringBuffer();
+
+        if ( clazz.isArray() ) {
+            name.append( canonicalName( clazz.getComponentType() ) );
+            name.append( "[]" );
+        } else if ( clazz.getDeclaringClass() == null ) {
+            name.append( clazz.getName() );
+        } else {
+            name.append( canonicalName( clazz.getDeclaringClass() ) );
+            name.append( "." );
+            name.append( clazz.getName().substring( clazz.getDeclaringClass().getName().length() + 1 ) );
+        }
+
+        return name.toString();
+    }
+
+    public static Object instantiateObject(String className) {
+        return instantiateObject( className,
+                                  null );
+    }
+
+    /**
+     * This method will attempt to create an instance of the specified Class. It uses
+     * a syncrhonized HashMap to cache the reflection Class lookup.
+     * @param className
+     * @return
+     */
+    public static Object instantiateObject(String className,
+                                           ClassLoader classLoader) {
+        Class cls = (Class) ClassUtils.classes.get( className );
+        if ( cls == null ) {
+            try {
+                cls = Class.forName( className );
+            } catch ( Exception e ) {
+                //swallow
+            }
+
+            //ConfFileFinder
+            if ( cls == null && classLoader != null ) {
+                try {
+                    cls = classLoader.loadClass( className );
+                } catch ( Exception e ) {
+                    //swallow
+                }
+            }
+
+            if ( cls == null ) {
+                try {
+                    cls = ClassUtils.class.getClassLoader().loadClass( className );
+                } catch ( Exception e ) {
+                    //swallow
+                }
+            }
+
+            if ( cls == null ) {
+                try {
+                    cls = Thread.currentThread().getContextClassLoader().loadClass( className );
+                } catch ( Exception e ) {
+                    //swallow
+                }
+            }
+
+            if ( cls == null ) {
+                try {
+                    cls = ClassLoader.getSystemClassLoader().loadClass( className );
+                } catch ( Exception e ) {
+                    //swallow
+                }
+            }
+            
+            if ( cls != null ) {
+                ClassUtils.classes.put( className,
+                                        cls );
+            } else {
+                throw new RuntimeException( "Unable to load class '" + className + "'" );
+            }
+        }
+
+        Object object = null;
+        try {
+            object = cls.newInstance();
+        } catch ( Throwable e ) {
+            throw new RuntimeException( "Unable to instantiate object for class '" + className + "'",
+                                        e );
+        }
+        return object;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/CompositeCollection.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/CompositeCollection.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/CompositeCollection.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,514 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.util;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+
+/**
+ * Decorates a collection of other collections to provide a single unified view.
+ * <p>
+ * Changes made to this collection will actually be made on the decorated
+ * collection. Add and remove operations require the use of a pluggable
+ * strategy. If no strategy is provided then add and remove are unsupported.
+ * 
+ * @since Commons Collections 3.0
+ * @version $Revision: 1.1 $ $Date: 2005/07/26 01:06:32 $
+ * 
+ * @author Brian McCallister
+ * @author Stephen Colebourne
+ * @author Phil Steitz
+ */
+public class CompositeCollection
+    implements
+    Collection {
+
+    /** CollectionMutator to handle changes to the collection */
+    protected CollectionMutator mutator;
+
+    /** Collections in the composite */
+    protected Collection[]      all;
+
+    /**
+     * Create an empty CompositeCollection.
+     */
+    public CompositeCollection() {
+        super();
+        this.all = new Collection[0];
+    }
+
+    /**
+     * Create a Composite Collection with only coll composited.
+     * 
+     * @param coll
+     *            a collection to decorate
+     */
+    public CompositeCollection(final Collection coll) {
+        this();
+        this.addComposited( coll );
+    }
+
+    /**
+     * Create a CompositeCollection with colls as the initial list of composited
+     * collections.
+     * 
+     * @param colls
+     *            an array of collections to decorate
+     */
+    public CompositeCollection(final Collection[] colls) {
+        this();
+        this.addComposited( colls );
+    }
+
+    // -----------------------------------------------------------------------
+    /**
+     * Gets the size of this composite collection.
+     * <p>
+     * This implementation calls <code>size()</code> on each collection.
+     * 
+     * @return total number of elements in all contained containers
+     */
+    public int size() {
+        int size = 0;
+        for ( int i = this.all.length - 1; i >= 0; i-- ) {
+            size += this.all[i].size();
+        }
+        return size;
+    }
+
+    /**
+     * Checks whether this composite collection is empty.
+     * <p>
+     * This implementation calls <code>isEmpty()</code> on each collection.
+     * 
+     * @return true if all of the contained collections are empty
+     */
+    public boolean isEmpty() {
+        for ( int i = this.all.length - 1; i >= 0; i-- ) {
+            if ( this.all[i].isEmpty() == false ) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Checks whether this composite collection contains the object.
+     * <p>
+     * This implementation calls <code>contains()</code> on each collection.
+     * 
+     * @param obj
+     *            the object to search for
+     * @return true if obj is contained in any of the contained collections
+     */
+    public boolean contains(final Object obj) {
+        for ( int i = this.all.length - 1; i >= 0; i-- ) {
+            if ( this.all[i].contains( obj ) ) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Gets an iterator over all the collections in this composite.
+     * <p>
+     * This implementation uses an <code>IteratorChain</code>.
+     * 
+     * @return an <code>IteratorChain</code> instance which supports
+     *         <code>remove()</code>. Iteration occurs over contained
+     *         collections in the order they were added, but this behavior
+     *         should not be relied upon.
+     * @see IteratorChain
+     */
+    public Iterator iterator() {
+        if ( this.all.length == 0 ) {
+            return Collections.EMPTY_LIST.iterator();
+        }
+        final IteratorChain chain = new IteratorChain();
+        for ( int i = 0; i < this.all.length; ++i ) {
+            chain.addIterator( this.all[i].iterator() );
+        }
+        return chain;
+    }
+
+    /**
+     * Returns an array containing all of the elements in this composite.
+     * 
+     * @return an object array of all the elements in the collection
+     */
+    public Object[] toArray() {
+        final Object[] result = new Object[this.size()];
+        int i = 0;
+        for ( final Iterator it = this.iterator(); it.hasNext(); i++ ) {
+            result[i] = it.next();
+        }
+        return result;
+    }
+
+    /**
+     * Returns an object array, populating the supplied array if possible. See
+     * <code>Collection</code> interface for full details.
+     * 
+     * @param array
+     *            the array to use, populating if possible
+     * @return an array of all the elements in the collection
+     */
+    public Object[] toArray(final Object[] array) {
+        final int size = this.size();
+        Object[] result;
+        if ( array.length >= size ) {
+            result = array;
+        } else {
+            result = (Object[]) Array.newInstance( array.getClass().getComponentType(),
+                                                   size );
+        }
+
+        int offset = 0;
+        for ( int i = 0; i < this.all.length; ++i ) {
+            for ( final Iterator it = this.all[i].iterator(); it.hasNext(); ) {
+                result[offset++] = it.next();
+            }
+        }
+        if ( result.length > size ) {
+            result[size] = null;
+        }
+        return result;
+    }
+
+    /**
+     * Adds an object to the collection, throwing UnsupportedOperationException
+     * unless a CollectionMutator strategy is specified.
+     * 
+     * @param obj
+     *            the object to add
+     * @return true if the collection was modified
+     * @throws UnsupportedOperationException
+     *             if CollectionMutator hasn't been set
+     * @throws UnsupportedOperationException
+     *             if add is unsupported
+     * @throws ClassCastException
+     *             if the object cannot be added due to its type
+     * @throws NullPointerException
+     *             if the object cannot be added because its null
+     * @throws IllegalArgumentException
+     *             if the object cannot be added
+     */
+    public boolean add(final Object obj) {
+        if ( this.mutator == null ) {
+            throw new UnsupportedOperationException( "add() is not supported on CompositeCollection without a CollectionMutator strategy" );
+        }
+        return this.mutator.add( this,
+                                 this.all,
+                                 obj );
+    }
+
+    /**
+     * Removes an object from the collection, throwing
+     * UnsupportedOperationException unless a CollectionMutator strategy is
+     * specified.
+     * 
+     * @param obj
+     *            the object being removed
+     * @return true if the collection is changed
+     * @throws UnsupportedOperationException
+     *             if removed is unsupported
+     * @throws ClassCastException
+     *             if the object cannot be removed due to its type
+     * @throws NullPointerException
+     *             if the object cannot be removed because its null
+     * @throws IllegalArgumentException
+     *             if the object cannot be removed
+     */
+    public boolean remove(final Object obj) {
+        if ( this.mutator == null ) {
+            throw new UnsupportedOperationException( "remove() is not supported on CompositeCollection without a CollectionMutator strategy" );
+        }
+        return this.mutator.remove( this,
+                                    this.all,
+                                    obj );
+    }
+
+    /**
+     * Checks whether this composite contains all the elements in the specified
+     * collection.
+     * <p>
+     * This implementation calls <code>contains()</code> for each element in
+     * the specified collection.
+     * 
+     * @param coll
+     *            the collection to check for
+     * @return true if all elements contained
+     */
+    public boolean containsAll(final Collection coll) {
+        for ( final Iterator it = coll.iterator(); it.hasNext(); ) {
+            if ( this.contains( it.next() ) == false ) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Adds a collection of elements to this collection, throwing
+     * UnsupportedOperationException unless a CollectionMutator strategy is
+     * specified.
+     * 
+     * @param coll
+     *            the collection to add
+     * @return true if the collection was modified
+     * @throws UnsupportedOperationException
+     *             if CollectionMutator hasn't been set
+     * @throws UnsupportedOperationException
+     *             if add is unsupported
+     * @throws ClassCastException
+     *             if the object cannot be added due to its type
+     * @throws NullPointerException
+     *             if the object cannot be added because its null
+     * @throws IllegalArgumentException
+     *             if the object cannot be added
+     */
+    public boolean addAll(final Collection coll) {
+        if ( this.mutator == null ) {
+            throw new UnsupportedOperationException( "addAll() is not supported on CompositeCollection without a CollectionMutator strategy" );
+        }
+        return this.mutator.addAll( this,
+                                    this.all,
+                                    coll );
+    }
+
+    /**
+     * Removes the elements in the specified collection from this composite
+     * collection.
+     * <p>
+     * This implementation calls <code>removeAll</code> on each collection.
+     * 
+     * @param coll
+     *            the collection to remove
+     * @return true if the collection was modified
+     * @throws UnsupportedOperationException
+     *             if removeAll is unsupported
+     */
+    public boolean removeAll(final Collection coll) {
+        if ( coll.isEmpty() ) {
+            return false;
+        }
+
+        boolean changed = false;
+        for ( int i = this.all.length - 1; i >= 0; i-- ) {
+            changed |= this.all[i].removeAll( coll );
+        }
+        return changed;
+    }
+
+    /**
+     * Retains all the elements in the specified collection in this composite
+     * collection, removing all others.
+     * <p>
+     * This implementation calls <code>retainAll()</code> on each collection.
+     * 
+     * @param coll
+     *            the collection to remove
+     * @return true if the collection was modified
+     * @throws UnsupportedOperationException
+     *             if retainAll is unsupported
+     */
+    public boolean retainAll(final Collection coll) {
+        boolean changed = false;
+        for ( int i = this.all.length - 1; i >= 0; i-- ) {
+            changed = (this.all[i].retainAll( coll ) || changed);
+        }
+        return changed;
+    }
+
+    /**
+     * Removes all of the elements from this collection .
+     * <p>
+     * This implementation calls <code>clear()</code> on each collection.
+     * 
+     * @throws UnsupportedOperationException
+     *             if clear is unsupported
+     */
+    public void clear() {
+        for ( int i = 0; i < this.all.length; ++i ) {
+            this.all[i].clear();
+        }
+    }
+
+    // -----------------------------------------------------------------------
+    /**
+     * Specify a CollectionMutator strategy instance to handle changes.
+     * 
+     * @param mutator
+     *            the mutator to use
+     */
+    public void setMutator(final CollectionMutator mutator) {
+        this.mutator = mutator;
+    }
+
+    /**
+     * Add these Collections to the list of collections in this composite
+     * 
+     * @param comps
+     *            Collections to be appended to the composite
+     */
+    public void addComposited(final Collection[] comps) {
+        final ArrayList list = new ArrayList( Arrays.asList( this.all ) );
+        list.addAll( Arrays.asList( comps ) );
+        this.all = (Collection[]) list.toArray( new Collection[list.size()] );
+    }
+
+    /**
+     * Add an additional collection to this composite.
+     * 
+     * @param c
+     *            the collection to add
+     */
+    public void addComposited(final Collection c) {
+        this.addComposited( new Collection[]{c} );
+    }
+
+    /**
+     * Add two additional collections to this composite.
+     * 
+     * @param c
+     *            the first collection to add
+     * @param d
+     *            the second collection to add
+     */
+    public void addComposited(final Collection c,
+                              final Collection d) {
+        this.addComposited( new Collection[]{c, d} );
+    }
+
+    /**
+     * Removes a collection from the those being decorated in this composite.
+     * 
+     * @param coll
+     *            collection to be removed
+     */
+    public void removeComposited(final Collection coll) {
+        final ArrayList list = new ArrayList( this.all.length );
+        list.addAll( Arrays.asList( this.all ) );
+        list.remove( coll );
+        this.all = (Collection[]) list.toArray( new Collection[list.size()] );
+    }
+
+    /**
+     * Returns a new collection containing all of the elements
+     * 
+     * @return A new ArrayList containing all of the elements in this composite.
+     *         The new collection is <i>not </i> backed by this composite.
+     */
+    public Collection toCollection() {
+        return new ArrayList( this );
+    }
+
+    /**
+     * Gets the collections being decorated.
+     * 
+     * @return Unmodifiable collection of all collections in this composite.
+     */
+    public Collection getCollections() {
+        return Collections.unmodifiableList( Arrays.asList( this.all ) );
+    }
+
+    // -----------------------------------------------------------------------
+    /**
+     * Pluggable strategy to handle changes to the composite.
+     */
+    public interface CollectionMutator {
+
+        /**
+         * Called when an object is to be added to the composite.
+         * 
+         * @param composite
+         *            the CompositeCollection being changed
+         * @param collections
+         *            all of the Collection instances in this
+         *            CompositeCollection
+         * @param obj
+         *            the object being added
+         * @return true if the collection is changed
+         * @throws UnsupportedOperationException
+         *             if add is unsupported
+         * @throws ClassCastException
+         *             if the object cannot be added due to its type
+         * @throws NullPointerException
+         *             if the object cannot be added because its null
+         * @throws IllegalArgumentException
+         *             if the object cannot be added
+         */
+        public boolean add(CompositeCollection composite,
+                           Collection[] collections,
+                           Object obj);
+
+        /**
+         * Called when a collection is to be added to the composite.
+         * 
+         * @param composite
+         *            the CompositeCollection being changed
+         * @param collections
+         *            all of the Collection instances in this
+         *            CompositeCollection
+         * @param coll
+         *            the collection being added
+         * @return true if the collection is changed
+         * @throws UnsupportedOperationException
+         *             if add is unsupported
+         * @throws ClassCastException
+         *             if the object cannot be added due to its type
+         * @throws NullPointerException
+         *             if the object cannot be added because its null
+         * @throws IllegalArgumentException
+         *             if the object cannot be added
+         */
+        public boolean addAll(CompositeCollection composite,
+                              Collection[] collections,
+                              Collection coll);
+
+        /**
+         * Called when an object is to be removed to the composite.
+         * 
+         * @param composite
+         *            the CompositeCollection being changed
+         * @param collections
+         *            all of the Collection instances in this
+         *            CompositeCollection
+         * @param obj
+         *            the object being removed
+         * @return true if the collection is changed
+         * @throws UnsupportedOperationException
+         *             if removed is unsupported
+         * @throws ClassCastException
+         *             if the object cannot be removed due to its type
+         * @throws NullPointerException
+         *             if the object cannot be removed because its null
+         * @throws IllegalArgumentException
+         *             if the object cannot be removed
+         */
+        public boolean remove(CompositeCollection composite,
+                              Collection[] collections,
+                              Object obj);
+
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ConfFileUtils.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ConfFileUtils.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ConfFileUtils.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,147 @@
+/**
+ * 
+ */
+package org.drools.util;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Properties;
+
+public class ConfFileUtils {
+   
+    /**
+     * Return the URL for a given conf file
+     * @param confName
+     * @param classLoader
+     * @return
+     */
+    public static URL getURL(String confName, ClassLoader classLoader, Class cls) {
+        URL url = null;
+        
+        // User home 
+        String userHome = System.getProperty( "user.home" );
+        if ( userHome.endsWith( "\\" ) || userHome.endsWith( "/" ) ) {
+            url = getURLForFile( userHome + confName );
+        } else {
+            url = getURLForFile( userHome + "/" + confName );
+        }
+
+        // Working directory             
+        if ( url == null ) {
+            url = getURLForFile( confName );
+        }
+        
+        // check Class folder
+        if ( cls != null ) {
+            url = cls.getResource( confName );
+        }
+
+        // check META-INF directories for all known ClassLoaders
+        if ( url == null && classLoader != null ) {
+            ClassLoader confClassLoader = classLoader;
+            if ( confClassLoader != null ) {
+                url = confClassLoader.getResource( "META-INF/" + confName );
+            }
+        }
+
+        if ( url == null ) {
+            ClassLoader confClassLoader = ConfFileUtils.class.getClassLoader();
+            if ( confClassLoader != null && confClassLoader != classLoader ) {
+                url = confClassLoader.getResource( "META-INF/" + confName );
+            }
+        }
+        
+        if ( url == null && cls != null ) {
+            ClassLoader confClassLoader = cls.getClassLoader();
+            if ( confClassLoader != null && confClassLoader != classLoader ) {
+                url = confClassLoader.getResource( "META-INF/" + confName );
+            }
+        }        
+
+        if ( url == null ) {
+            ClassLoader confClassLoader = Thread.currentThread().getContextClassLoader();
+            if ( confClassLoader != null && confClassLoader != classLoader ) {
+                url = confClassLoader.getResource( "META-INF/" + confName );
+            }
+        }
+
+        if ( url == null ) {
+            ClassLoader confClassLoader = ClassLoader.getSystemClassLoader();
+            if ( confClassLoader != null && confClassLoader != classLoader ) {
+                url = confClassLoader.getResource( "META-INF/" + confName );
+            }
+        }
+
+        return url;          
+    }
+    
+    /**
+     * Return URL for given filename
+     * 
+     * @param fileName
+     * @return
+     *  URL
+     */
+    public static URL getURLForFile(String fileName) {
+        URL url = null;
+        if ( fileName != null ) {
+            File file = new File( fileName );
+            if ( file != null && file.exists() ) {
+                try {
+                    url = file.toURL();
+                } catch ( MalformedURLException e ) {
+                    throw new IllegalArgumentException( "file.toURL() failed for '" + file + "'" );
+                }
+            } 
+        }
+        return url;
+    }     
+    
+    public static String URLContentsToString(URL url) {
+        StringBuilder builder = new StringBuilder();
+        if ( url == null ) {
+            return null;
+        }
+        
+        try {
+            BufferedReader reader = new BufferedReader(new InputStreamReader( url.openStream() ));
+            String line = null;
+        
+            while ( ( line = reader.readLine() ) != null ) { // while loop begins here
+                builder.append( line );
+                builder.append( "\n" );
+            }
+        } catch ( IOException e ) {
+            throw new RuntimeException( "Unable to read " + url.toExternalForm() );
+        }        
+        return builder.toString();
+    }
+    
+    /**
+     * Load a Properties file from a URL, return null if it fails
+     * 
+     * @param url
+     * @return
+     *  URL
+     */
+    public static Properties getProperties(URL url) {
+        if ( url == null ) {
+            return null;
+        }
+        
+        Properties properties = new Properties();
+        try {
+            properties.load( url.openStream() );
+        } catch ( IOException e ) {
+            //swallow, as we'll return null
+            return null;
+        }       
+        
+        return properties;
+    }
+                   
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/DateUtils.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/DateUtils.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/DateUtils.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Dec 6, 2007
+ */
+package org.drools.util;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * @author etirelli
+ *
+ */
+public class DateUtils {
+    
+    private static final long       serialVersionUID    = 400L;
+    private static final String     DEFAULT_FORMAT_MASK = "dd-MMM-yyyy";
+    private static final String     DATE_FORMAT_MASK    = getDateFormatMask();
+    private static SimpleDateFormat df = new SimpleDateFormat( DATE_FORMAT_MASK );
+    
+    
+    /** Use the simple date formatter to read the date from a string */
+    public static Date parseDate(final String input) {
+        try {
+            return df.parse( input );
+        } catch ( final ParseException e ) {
+            throw new IllegalArgumentException( "Invalid date input format: [" + input + "] it should follow: [" + DATE_FORMAT_MASK + "]" );
+        }
+    }
+
+    /** Converts the right hand side date as appropriate */
+    public static Date getRightDate(final Object object2) {
+        if ( object2 == null ) {
+            return null;
+        }
+        if ( object2 instanceof String ) {
+            return parseDate( (String) object2 );
+        } else if ( object2 instanceof Date ) {
+            return (Date) object2;
+        } else {
+            throw new IllegalArgumentException( "Unable to convert " + object2.getClass() + " to a Date." );
+        }
+    }
+
+    /** Check for the system property override, if it exists */
+    public static String getDateFormatMask() {
+        String fmt = System.getProperty( "drools.dateformat" );
+        if ( fmt == null ) {
+            fmt = DEFAULT_FORMAT_MASK;
+        }
+        return fmt;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/Entry.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/Entry.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/Entry.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,14 @@
+/**
+ * 
+ */
+package org.drools.util;
+
+import java.io.Serializable;
+
+public interface Entry
+    extends
+    Serializable {
+    public void setNext(Entry next);
+
+    public Entry getNext();
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/FactEntry.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/FactEntry.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/FactEntry.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,7 @@
+package org.drools.util;
+
+import org.drools.common.InternalFactHandle;
+
+public interface FactEntry {
+    public InternalFactHandle getFactHandle();
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/FactHandleIndexHashTable.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/FactHandleIndexHashTable.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/FactHandleIndexHashTable.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,371 @@
+/**
+ * 
+ */
+package org.drools.util;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.reteoo.FactHandleMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.util.TupleIndexHashTable.FieldIndexEntry;
+
+public class FactHandleIndexHashTable extends AbstractHashTable
+    implements
+    FactHandleMemory {
+
+    private static final long           serialVersionUID = 400L;
+
+    public static final int             PRIME            = 31;
+
+    private int                         startResult;
+
+    private FieldIndexHashTableIterator tupleValueIterator;
+
+    private int                         factSize;
+
+    private Index                       index;
+
+    public FactHandleIndexHashTable(final FieldIndex[] index) {
+        this( 16,
+              0.75f,
+              index );
+    }
+
+    public FactHandleIndexHashTable(final int capacity,
+                                    final float loadFactor,
+                                    final FieldIndex[] index) {
+        super( capacity,
+               loadFactor );
+
+        this.startResult = FactHandleIndexHashTable.PRIME;
+        for ( int i = 0, length = index.length; i < length; i++ ) {
+            this.startResult = FactHandleIndexHashTable.PRIME * this.startResult + index[i].getExtractor().getIndex();
+        }
+
+        switch ( index.length ) {
+            case 0 :
+                throw new IllegalArgumentException( "FieldIndexHashTable cannot use an index[] of length  0" );
+            case 1 :
+                this.index = new SingleIndex( index,
+                                              this.startResult );
+                break;
+            case 2 :
+                this.index = new DoubleCompositeIndex( index,
+                                                       this.startResult );
+                break;
+            case 3 :
+                this.index = new TripleCompositeIndex( index,
+                                                       this.startResult );
+                break;
+            default :
+                throw new IllegalArgumentException( "FieldIndexHashTable cannot use an index[] of length  great than 3" );
+        }
+    }
+
+    public Iterator iterator() {
+        throw new UnsupportedOperationException( "FieldIndexHashTable does not support  iterator()" );
+    }
+
+    public Iterator iterator(final ReteTuple tuple) {
+        if ( this.tupleValueIterator == null ) {
+            this.tupleValueIterator = new FieldIndexHashTableIterator();
+        }
+        final FieldIndexEntry entry = get( tuple );
+        this.tupleValueIterator.reset( (entry != null) ? entry.first : null );
+        return this.tupleValueIterator;
+    }
+
+    public boolean isIndexed() {
+        return true;
+    }
+    
+    public Index getIndex() {
+        return this.index;
+    }
+
+    public Entry getBucket(final Object object) {
+        final int hashCode = this.index.hashCodeOf( object );
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+
+        return this.table[index];
+    }
+
+    /**
+     * Fast re-usable iterator
+     *
+     */
+    public static class FieldIndexHashTableIterator
+        implements
+        Iterator {
+        private Entry entry;
+
+        public FieldIndexHashTableIterator() {
+
+        }
+
+        /* (non-Javadoc)
+         * @see org.drools.util.Iterator#next()
+         */
+        public Object next() {
+            final Entry current = this.entry;
+            this.entry = (this.entry != null) ? this.entry.getNext() : null;
+            return current;
+        }
+
+        /* (non-Javadoc)
+         * @see org.drools.util.Iterator#reset()
+         */
+        public void reset(final Entry entry) {
+            this.entry = entry;
+        }
+    }
+    
+    public Entry[] toArray() {
+        Entry[] result = new Entry[this.factSize];
+        int index = 0;
+        for ( int i = 0; i < this.table.length; i++ ) {
+            FieldIndexEntry fieldIndexEntry = (FieldIndexEntry)this.table[i];
+            while ( fieldIndexEntry != null ) {
+                Entry entry = fieldIndexEntry.getFirst();
+                while ( entry != null ) {
+                    result[index++] = entry;
+                    entry = entry.getNext();
+                }       
+                fieldIndexEntry  = ( FieldIndexEntry ) fieldIndexEntry.getNext();
+            }
+        }
+        return result;
+    }  
+
+    public boolean add(final InternalFactHandle handle) {
+        final FieldIndexEntry entry = getOrCreate( handle.getObject() );
+        entry.add( handle );
+        this.factSize++;
+        return true;
+    }
+
+    public boolean add(final InternalFactHandle handle,
+                       final boolean checkExists) {
+        throw new UnsupportedOperationException( "FieldIndexHashTable does not support add(InternalFactHandle handle, boolean checkExists)" );
+    }
+
+    public boolean remove(final InternalFactHandle handle) {
+        final Object object = handle.getObject();
+        //this.index.setCachedValue( object );
+        final int hashCode = this.index.hashCodeOf( object );
+
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+
+        // search the table for  the Entry, we need to track previous  and next, so if the 
+        // Entry is empty after  its had the FactEntry removed, we must remove  it from the table
+        FieldIndexEntry previous = (FieldIndexEntry) this.table[index];
+        FieldIndexEntry current = previous;
+        while ( current != null ) {
+            final FieldIndexEntry next = (FieldIndexEntry) current.next;
+            if ( current.matches( object,
+                                  hashCode ) ) {
+                current.remove( handle );
+                this.factSize--;
+                // If the FactEntryIndex is empty, then remove it from the hash table
+                if ( current.first == null ) {
+                    if ( previous == current ) {
+                        this.table[index] = next;
+                    } else {
+                        previous.next = next;
+                    }
+                    current.next = null;
+                    this.size--;
+                }
+                return true;
+            }
+            previous = current;
+            current = next;
+        }
+        return false;
+    }
+
+    public boolean contains(final InternalFactHandle handle) {
+        final Object object = handle.getObject();
+        //this.index.setCachedValue( object );
+
+        final int hashCode = this.index.hashCodeOf( object );
+
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+
+        FieldIndexEntry current = (FieldIndexEntry) this.table[index];
+        while ( current != null ) {
+            if ( current.matches( object,
+                                  hashCode ) ) {
+                return true;
+            }
+            current = (FieldIndexEntry) current.next;
+        }
+        return false;
+    }
+
+    public FieldIndexEntry get(final ReteTuple tuple) {
+        //this.index.setCachedValue( tuple );
+
+        final int hashCode = this.index.hashCodeOf( tuple );
+
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+        FieldIndexEntry entry = (FieldIndexEntry) this.table[index];
+
+        while ( entry != null ) {
+            if ( entry.matches( tuple,
+                                hashCode ) ) {
+                return entry;
+            }
+            entry = (FieldIndexEntry) entry.getNext();
+        }
+
+        return entry;
+    }
+
+    /**
+     * We use this method to aviod to table lookups for the same hashcode; which is what we would have to do if we did
+     * a get and then a create if the value is null.
+     * 
+     * @param value
+     * @return
+     */
+    private FieldIndexEntry getOrCreate(final Object object) {
+        //this.index.setCachedValue( object );
+
+        final int hashCode = this.index.hashCodeOf( object );
+
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+        FieldIndexEntry entry = (FieldIndexEntry) this.table[index];
+
+        while ( entry != null ) {
+            if ( entry.matches( object,
+                                hashCode ) ) {
+                return entry;
+            }
+            entry = (FieldIndexEntry) entry.next;
+        }
+
+        if ( entry == null ) {
+            entry = new FieldIndexEntry( this.index,
+                                         hashCode );
+            entry.next = this.table[index];
+            this.table[index] = entry;
+
+            if ( this.size++ >= this.threshold ) {
+                resize( 2 * this.table.length );
+            }
+        }
+        return entry;
+    }
+
+    public int size() {
+        return this.factSize;
+    }
+
+    public static class FieldIndexEntry
+        implements
+        Entry {
+
+        private static final long serialVersionUID = 400L;
+        private Entry             next;
+        private FactEntryImpl         first;
+        private final int         hashCode;
+        private Index             index;
+
+        public FieldIndexEntry(final Index index,
+                               final int hashCode) {
+            this.index = index;
+            this.hashCode = hashCode;
+        }
+
+        public Entry getNext() {
+            return this.next;
+        }
+
+        public void setNext(final Entry next) {
+            this.next = next;
+        }
+
+        public FactEntryImpl getFirst() {
+            return this.first;
+        }
+
+        public void add(final InternalFactHandle handle) {
+            final FactEntryImpl entry = new FactEntryImpl( handle );
+            entry.next = this.first;
+            this.first = entry;
+        }
+
+        public FactEntryImpl get(final InternalFactHandle handle) {
+            final long id = handle.getId();
+            FactEntryImpl current = this.first;
+            while ( current != null ) {
+                if ( current.handle.getId() == id ) {
+                    return current;
+                }
+                current = (FactEntryImpl) current.next;
+            }
+            return null;
+        }
+
+        public FactEntryImpl remove(final InternalFactHandle handle) {
+            final long id = handle.getId();
+
+            FactEntryImpl previous = this.first;
+            FactEntryImpl current = previous;
+            while ( current != null ) {
+                final FactEntryImpl next = (FactEntryImpl) current.next;
+                if ( current.handle.getId() == id ) {
+                    if ( this.first == current ) {
+                        this.first = next;
+                    } else {
+                        previous.next = next;
+                    }
+                    current.next = null;
+                    return current;
+                }
+                previous = current;
+                current = next;
+            }
+            return current;
+        }
+
+        //        public boolean matches(int otherHashCode) {
+        //            return this.hashCode == otherHashCode && this.index.equal( this.first.getFactHandle().getObject() );
+        //        }
+
+        public boolean matches(final Object object,
+                               final int objectHashCode) {
+            return this.hashCode == objectHashCode && this.index.equal( this.first.getFactHandle().getObject(),
+                                                                        object );
+        }
+
+        public boolean matches(final ReteTuple tuple,
+                               final int tupleHashCode) {
+            return this.hashCode == tupleHashCode && this.index.equal( this.first.getFactHandle().getObject(),
+                                                                       tuple );
+        }
+
+        public int hashCode() {
+            return this.hashCode;
+        }
+
+        public boolean equals(final Object object) {
+            final FieldIndexEntry other = (FieldIndexEntry) object;
+            return this.hashCode == other.hashCode && this.index == other.index;
+        }
+
+        public String toString() {
+            return "FieldIndexEntry( hashCode=" + this.hashCode + " first=" + this.first + " )";
+        }
+    }
+
+	@Override
+	public InternalFactHandle peek() {
+		throw new UnsupportedOperationException( "FactHandleIndexHash does not support  peek()" );
+	}
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/FactHashTable.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/FactHashTable.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/FactHashTable.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,120 @@
+/**
+ * 
+ */
+package org.drools.util;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.reteoo.FactHandleMemory;
+import org.drools.reteoo.ReteTuple;
+
+public class FactHashTable extends AbstractHashTable
+    implements
+    FactHandleMemory {
+    private static final long serialVersionUID = 400L;
+
+    public FactHashTable() {
+        this( 16,
+              0.75f );
+    }
+
+    public FactHashTable(final int capacity,
+                         final float loadFactor) {
+        super( capacity,
+               loadFactor );
+    }
+
+    public Iterator iterator(final ReteTuple tuple) {
+        return iterator();
+    }
+
+    public boolean add(final InternalFactHandle handle) {
+        return add( handle,
+                    true );
+    }
+
+    public boolean add(final InternalFactHandle handle,
+                       final boolean checkExists) {
+        final int hashCode = this.comparator.hashCodeOf( handle );
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+
+        // scan the linked entries to see if it exists
+        if ( checkExists ) {
+            FactEntryImpl current = (FactEntryImpl) this.table[index];
+            while ( current != null ) {
+                if ( hashCode == current.hashCode && handle.getId() == current.handle.getId() ) {
+                    return false;
+                }
+                current = (FactHashTable.FactEntryImpl) current.getNext();
+            }
+        }
+
+        // We aren't checking the key exists, or it didn't find the key
+        final FactEntryImpl entry = new FactEntryImpl( handle,
+                                               hashCode );
+        entry.next = this.table[index];
+        this.table[index] = entry;
+
+        if ( this.size++ >= this.threshold ) {
+            resize( 2 * this.table.length );
+        }
+        return true;
+    }
+
+    public boolean contains(final InternalFactHandle handle) {
+        final int hashCode = this.comparator.hashCodeOf( handle );
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+
+        FactEntryImpl current = (FactEntryImpl) this.table[index];
+        while ( current != null ) {
+            if ( hashCode == current.hashCode && handle.getId() == current.handle.getId() ) {
+                return true;
+            }
+            current = (FactEntryImpl) current.getNext();
+        }
+        return false;
+    }
+
+    public boolean remove(final InternalFactHandle handle) {
+        final int hashCode = this.comparator.hashCodeOf( handle );
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+
+        FactEntryImpl previous = (FactEntryImpl) this.table[index];
+        FactEntryImpl current = previous;
+        while ( current != null ) {
+            final FactEntryImpl next = (FactEntryImpl) current.getNext();
+            if ( hashCode == current.hashCode && handle.getId() == current.handle.getId() ) {
+                if ( previous == current ) {
+                    this.table[index] = next;
+                } else {
+                    previous.setNext( next );
+                }
+                current.setNext( null );
+                this.size--;
+                return true;
+            }
+            previous = current;
+            current = next;
+        }
+        return false;
+    }
+
+    public Entry getBucket(final Object object) {
+        final int hashCode = this.comparator.hashCodeOf( object );
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+
+        return this.table[index];
+    }
+
+    public boolean isIndexed() {
+        return false;
+    }
+
+	@Override
+	public InternalFactHandle peek() {
+		throw new UnsupportedOperationException( "FactHashTable does not support  peek()" );
+	}
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/FactList.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/FactList.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/FactList.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,86 @@
+/**
+ * 
+ */
+package org.drools.util;
+
+import java.io.Serializable;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.reteoo.FactHandleMemory;
+import org.drools.reteoo.ReteTuple;
+
+public class FactList
+    implements
+    FactHandleMemory {
+    private static final long serialVersionUID = 400L;
+
+    private final LinkedList list;
+    
+    public FactList() {
+        this.list = new LinkedList();
+    }
+
+    public Iterator iterator(final ReteTuple tuple) {
+        return iterator();
+    }
+
+    public boolean add(final InternalFactHandle handle) {
+        return add( handle,
+                    true );
+    }
+
+    public boolean add(final InternalFactHandle handle,
+                       final boolean checkExists) {
+        this.list.add( new FactEntryImpl( handle ) );
+        return true;
+    }
+
+    public boolean contains(final InternalFactHandle handle) {
+        Iterator it = this.list.iterator();
+        for ( Object object = it.next(); object != null; object = it.next() ) {
+            if ( handle.equals( ((LinkedListEntry)object).getObject() ) ) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean remove(final InternalFactHandle handle) {
+        Iterator it = this.list.iterator();
+        for ( Object object = it.next(); object != null; object = it.next() ) {
+            if ( handle.equals( ((LinkedListEntry)object).getObject() ) ) {
+                this.list.remove( (LinkedListEntry)object );
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    public Iterator iterator() {
+        return this.list.iterator();
+    }
+
+    public int size() {
+        return  this.list.size();
+    }
+
+    public boolean isIndexed() {
+        return false;
+    }
+    
+    public static class FactEntryImpl extends LinkedListEntry implements FactEntry, Serializable {    
+        public FactEntryImpl(InternalFactHandle handle) {
+            super(handle);
+        }
+
+        public InternalFactHandle getFactHandle() {
+            return (InternalFactHandle) getObject();
+        }
+        
+    }
+
+	@Override
+	public InternalFactHandle peek() {
+		throw new UnsupportedOperationException( "FactList does not support  peek()" );
+	}
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/Iterator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/Iterator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/Iterator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,9 @@
+package org.drools.util;
+
+import java.io.Serializable;
+
+public interface Iterator
+    extends
+    Serializable {
+    public Object next();
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/IteratorChain.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/IteratorChain.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/IteratorChain.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,313 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * An IteratorChain is an Iterator that wraps a number of Iterators.
+ * <p>
+ * This class makes multiple iterators look like one to the caller When any
+ * method from the Iterator interface is called, the IteratorChain will delegate
+ * to a single underlying Iterator. The IteratorChain will invoke the Iterators
+ * in sequence until all Iterators are exhausted.
+ * <p>
+ * Under many circumstances, linking Iterators together in this manner is more
+ * efficient (and convenient) than reading out the contents of each Iterator
+ * into a List and creating a new Iterator.
+ * <p>
+ * Calling a method that adds new Iterator <i>after a method in the Iterator
+ * interface has been called </i> will result in an
+ * UnsupportedOperationException. Subclasses should <i>take care </i> to not
+ * alter the underlying List of Iterators.
+ * <p>
+ * NOTE: As from version 3.0, the IteratorChain may contain no iterators. In
+ * this case the class will function as an empty iterator.
+ * 
+ * @since Commons Collections 2.1
+ * @version $Revision: 1.1 $ $Date: 2005/07/26 01:06:32 $
+ * 
+ * @author Morgan Delagrange
+ * @author Stephen Colebourne
+ */
+public class IteratorChain
+    implements
+    Iterator {
+
+    /** The chain of iterators */
+    protected final List iteratorChain        = new ArrayList();
+    /** The index of the current iterator */
+    protected int        currentIteratorIndex = 0;
+    /** The current iterator */
+    protected Iterator   currentIterator      = null;
+    /**
+     * The "last used" Iterator is the Iterator upon which next() or hasNext()
+     * was most recently called used for the remove() operation only
+     */
+    protected Iterator   lastUsedIterator     = null;
+    /**
+     * ComparatorChain is "locked" after the first time compare(Object,Object)
+     * is called
+     */
+    protected boolean    isLocked             = false;
+
+    // -----------------------------------------------------------------------
+    /**
+     * Construct an IteratorChain with no Iterators.
+     * <p>
+     * You will normally use {@link #addIterator(Iterator)}to add some
+     * iterators after using this constructor.
+     */
+    public IteratorChain() {
+        super();
+    }
+
+    /**
+     * Construct an IteratorChain with a single Iterator.
+     * 
+     * @param iterator
+     *            first Iterator in the IteratorChain
+     * @throws NullPointerException
+     *             if the iterator is null
+     */
+    public IteratorChain(final Iterator iterator) {
+        super();
+        addIterator( iterator );
+    }
+
+    /**
+     * Constructs a new <code>IteratorChain</code> over the two given
+     * iterators.
+     * 
+     * @param a
+     *            the first child iterator
+     * @param b
+     *            the second child iterator
+     * @throws NullPointerException
+     *             if either iterator is null
+     */
+    public IteratorChain(final Iterator a,
+                         final Iterator b) {
+        super();
+        addIterator( a );
+        addIterator( b );
+    }
+
+    /**
+     * Constructs a new <code>IteratorChain</code> over the array of
+     * iterators.
+     * 
+     * @param iterators
+     *            the array of iterators
+     * @throws NullPointerException
+     *             if iterators array is or contains null
+     */
+    public IteratorChain(final Iterator[] iterators) {
+        super();
+        for ( int i = 0; i < iterators.length; i++ ) {
+            addIterator( iterators[i] );
+        }
+    }
+
+    /**
+     * Constructs a new <code>IteratorChain</code> over the collection of
+     * iterators.
+     * 
+     * @param iterators
+     *            the collection of iterators
+     * @throws NullPointerException
+     *             if iterators collection is or contains null
+     * @throws ClassCastException
+     *             if iterators collection doesn't contain an iterator
+     */
+    public IteratorChain(final Collection iterators) {
+        super();
+        for ( final Iterator it = iterators.iterator(); it.hasNext(); ) {
+            final Iterator item = (Iterator) it.next();
+            addIterator( item );
+        }
+    }
+
+    // -----------------------------------------------------------------------
+    /**
+     * Add an Iterator to the end of the chain
+     * 
+     * @param iterator
+     *            Iterator to add
+     * @throws IllegalStateException
+     *             if I've already started iterating
+     * @throws NullPointerException
+     *             if the iterator is null
+     */
+    public void addIterator(final Iterator iterator) {
+        checkLocked();
+        if ( iterator == null ) {
+            throw new NullPointerException( "Iterator must not be null" );
+        }
+        this.iteratorChain.add( iterator );
+    }
+
+    /**
+     * Set the Iterator at the given index
+     * 
+     * @param index
+     *            index of the Iterator to replace
+     * @param iterator
+     *            Iterator to place at the given index
+     * @throws IndexOutOfBoundsException
+     *             if index &lt; 0 or index &gt; size()
+     * @throws IllegalStateException
+     *             if I've already started iterating
+     * @throws NullPointerException
+     *             if the iterator is null
+     */
+    public void setIterator(final int index,
+                            final Iterator iterator) throws IndexOutOfBoundsException {
+        checkLocked();
+        if ( iterator == null ) {
+            throw new NullPointerException( "Iterator must not be null" );
+        }
+        this.iteratorChain.set( index,
+                                iterator );
+    }
+
+    /**
+     * Get the list of Iterators (unmodifiable)
+     * 
+     * @return the unmodifiable list of iterators added
+     */
+    public List getIterators() {
+        return Collections.unmodifiableList( this.iteratorChain );
+    }
+
+    /**
+     * Number of Iterators in the current IteratorChain.
+     * 
+     * @return Iterator count
+     */
+    public int size() {
+        return this.iteratorChain.size();
+    }
+
+    /**
+     * Determine if modifications can still be made to the IteratorChain.
+     * IteratorChains cannot be modified once they have executed a method from
+     * the Iterator interface.
+     * 
+     * @return true if IteratorChain cannot be modified, false if it can
+     */
+    public boolean isLocked() {
+        return this.isLocked;
+    }
+
+    /**
+     * Checks whether the iterator chain is now locked and in use.
+     */
+    private void checkLocked() {
+        if ( this.isLocked == true ) {
+            throw new UnsupportedOperationException( "IteratorChain cannot be changed after the first use of a method from the Iterator interface" );
+        }
+    }
+
+    /**
+     * Lock the chain so no more iterators can be added. This must be called
+     * from all Iterator interface methods.
+     */
+    private void lockChain() {
+        if ( this.isLocked == false ) {
+            this.isLocked = true;
+        }
+    }
+
+    /**
+     * Updates the current iterator field to ensure that the current Iterator is
+     * not exhausted
+     */
+    protected void updateCurrentIterator() {
+        if ( this.currentIterator == null ) {
+            if ( this.iteratorChain.isEmpty() ) {
+                this.currentIterator = Collections.EMPTY_LIST.iterator();
+            } else {
+                this.currentIterator = (Iterator) this.iteratorChain.get( 0 );
+            }
+            // set last used iterator here, in case the user calls remove
+            // before calling hasNext() or next() (although they shouldn't)
+            this.lastUsedIterator = this.currentIterator;
+        }
+
+        while ( this.currentIterator.hasNext() == false && this.currentIteratorIndex < this.iteratorChain.size() - 1 ) {
+            this.currentIteratorIndex++;
+            this.currentIterator = (Iterator) this.iteratorChain.get( this.currentIteratorIndex );
+        }
+    }
+
+    // -----------------------------------------------------------------------
+    /**
+     * Return true if any Iterator in the IteratorChain has a remaining element.
+     * 
+     * @return true if elements remain
+     */
+    public boolean hasNext() {
+        lockChain();
+        updateCurrentIterator();
+        this.lastUsedIterator = this.currentIterator;
+
+        return this.currentIterator.hasNext();
+    }
+
+    /**
+     * Returns the next Object of the current Iterator
+     * 
+     * @return Object from the current Iterator
+     * @throws java.util.NoSuchElementException
+     *             if all the Iterators are exhausted
+     */
+    public Object next() {
+        lockChain();
+        updateCurrentIterator();
+        this.lastUsedIterator = this.currentIterator;
+
+        return this.currentIterator.next();
+    }
+
+    /**
+     * Removes from the underlying collection the last element returned by the
+     * Iterator. As with next() and hasNext(), this method calls remove() on the
+     * underlying Iterator. Therefore, this method may throw an
+     * UnsupportedOperationException if the underlying Iterator does not support
+     * this method.
+     * 
+     * @throws UnsupportedOperationException
+     *             if the remove operator is not supported by the underlying
+     *             Iterator
+     * @throws IllegalStateException
+     *             if the next method has not yet been called, or the remove
+     *             method has already been called after the last call to the
+     *             next method.
+     */
+    public void remove() {
+        lockChain();
+        updateCurrentIterator();
+
+        this.lastUsedIterator.remove();
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/JavaIteratorAdapter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/JavaIteratorAdapter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/JavaIteratorAdapter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,87 @@
+package org.drools.util;
+
+import java.util.NoSuchElementException;
+
+import org.drools.FactHandle;
+import org.drools.ObjectFilter;
+import org.drools.base.ShadowProxy;
+import org.drools.common.InternalFactHandle;
+import org.drools.util.ObjectHashMap.ObjectEntry;
+
+public class JavaIteratorAdapter
+    implements
+    java.util.Iterator {
+    public static int    OBJECT = 0;
+    public static int    FACT_HANDLE = 1;
+
+    private Iterator     iterator;
+    private ObjectEntry  nextEntry;
+    //    private Object  nextObject;
+    //    private InternalFactHandle  nextHandle;
+    private ObjectFilter filter;
+    private int          type;
+
+    public JavaIteratorAdapter(Iterator iterator,
+                               int type) {
+        this( iterator,
+              type,
+              null );
+    }
+
+    public JavaIteratorAdapter(Iterator iterator,
+                               int type,
+                               ObjectFilter filter) {
+        this.iterator = iterator;
+        this.filter = filter;
+        this.type = type;
+        setNext();
+    }
+
+    public boolean hasNext() {
+        return (this.nextEntry != null);
+    }
+
+    public Object next() {
+        ObjectEntry current = this.nextEntry;
+
+        if ( current != null ) {
+            setNext();
+        } else {
+            throw new NoSuchElementException( "No more elements to return" );
+        }
+
+        if ( this.type == OBJECT ) {
+            InternalFactHandle handle = (InternalFactHandle) current.getKey();
+            Object object = (handle.isShadowFact()) ? ((ShadowProxy) handle.getObject()).getShadowedObject() : handle.getObject();
+            return object;
+        } else {
+            return current.getKey();
+        }
+    }
+
+    private void setNext() {
+        ObjectEntry entry = null;
+
+        while ( entry == null ) {
+            entry = (ObjectEntry) this.iterator.next();
+            if ( entry == null ) {
+                break;
+            }
+            if ( this.filter != null ) {
+                InternalFactHandle handle = (InternalFactHandle) entry.getKey();
+                Object object = (handle.isShadowFact()) ? ((ShadowProxy) handle.getObject()).getShadowedObject() : handle.getObject();
+                if ( this.filter.accept( object ) == false ) {
+                    entry = null;
+                }
+            }
+        }
+
+        this.nextEntry = entry;
+        //        this.nextHandle = handle;
+        //        this.nextObject = object;
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException( "remove() is not support" );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/LinkedList.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/LinkedList.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/LinkedList.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,340 @@
+package org.drools.util;
+
+import java.io.Serializable;
+import java.util.NoSuchElementException;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * This is a simple linked linked implementation. Each node must implement </code>LinkedListNode<code> so that it references
+ * the node before and after it. This way a node can be removed without having to scan the list to find it. This class
+ * does not provide an Iterator implementation as its designed for efficiency and not genericity. There are a number of 
+ * ways to iterate the list.
+ * <p>
+ * Simple iterator:
+ * <pre>
+ * for ( LinkedListNode node = list.getFirst(); node != null; node =  node.getNext() ) {
+ * }
+ * </pre>
+ * 
+ * Iterator that pops the first entry:
+ * <pre>
+ * for ( LinkedListNode node = list.removeFirst(); node != null; node = list.removeFirst() ) {
+ * }
+ * </pre>
+ *
+ *
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ *
+ */
+public class LinkedList
+    implements
+    Serializable {
+    private static final long  serialVersionUID = 400L;
+
+    private LinkedListNode     firstNode;
+    private LinkedListNode     lastNode;
+
+    private int                size;
+
+    private LinkedListIterator iterator;
+
+    /**
+     * Construct an empty <code>LinkedList</code>
+     */
+    public LinkedList() {
+        this.iterator = new LinkedListIterator();
+    }
+
+    /**
+     * Add a <code>LinkedListNode</code> to the list. If the <code>LinkedList</code> is empty then the first and 
+     * last nodes are set to the added node.
+     * 
+     * @param node
+     *      The <code>LinkedListNode</code> to be added
+     */
+    public void add(final LinkedListNode node) {
+        if ( this.firstNode == null ) {
+            this.firstNode = node;
+            this.lastNode = node;;
+        } else {
+            this.lastNode.setNext( node );
+            node.setPrevious( this.lastNode );
+            this.lastNode = node;
+        }
+        this.size++;
+    }
+
+    /**
+     * Removes a <code>LinkedListNode</code> from the list. This works by attach the previous reference to the child reference.
+     * When the node to be removed is the first node it calls <code>removeFirst()</code>. When the node to be removed is the last node
+     * it calls <code>removeLast()</code>.
+     * 
+     * @param node
+     *      The <code>LinkedListNode</code> to be removed.
+     */
+    public void remove(final LinkedListNode node) {
+        if ( this.firstNode == node ) {
+            removeFirst();
+        } else if ( this.lastNode == node ) {
+            removeLast();
+        } else {
+            node.getPrevious().setNext( node.getNext() );
+            (node.getNext()).setPrevious( node.getPrevious() );
+            this.size--;
+            node.setPrevious( null );
+            node.setNext( null );
+        }
+    }
+
+    /**
+     * Return the first node in the list
+     * @return
+     *      The first <code>LinkedListNode</code>.
+     */
+    public final LinkedListNode getFirst() {
+        return this.firstNode;
+    }
+
+    /**
+     * Return the last node in the list
+     * @return
+     *      The last <code>LinkedListNode</code>.
+     */
+    public final LinkedListNode getLast() {
+        return this.lastNode;
+    }
+
+    /**
+     * Remove the first node from the list. The next node then becomes the first node. If this is the last 
+     * node then both first and last node references are set to null.
+     * 
+     * @return
+     *      The first <code>LinkedListNode</code>.
+     */
+    public LinkedListNode removeFirst() {
+        if ( this.firstNode == null ) {
+            return null;
+        }
+        final LinkedListNode node = this.firstNode;
+        this.firstNode = node.getNext();
+        node.setNext( null );
+        if ( this.firstNode != null ) {
+            this.firstNode.setPrevious( null );
+        } else {
+            this.lastNode = null;
+        }
+        this.size--;
+        return node;
+    }
+
+    public void insertAfter(final LinkedListNode existingNode,
+                            final LinkedListNode newNode) {
+        if ( newNode.getPrevious() != null || newNode.getNext() != null ) {
+            //do nothing if this node is already inserted somewhere
+            return;
+        }
+
+        if ( existingNode == null ) {
+            if ( this.isEmpty() ) {
+                this.firstNode = newNode;
+                this.lastNode = newNode;
+            } else {
+                // if existing node is null, then insert it as a first node
+                final LinkedListNode node = this.firstNode;
+                node.setPrevious( newNode );
+                newNode.setNext( node );
+                this.firstNode = newNode;
+            }
+        } else if ( existingNode == this.lastNode ) {
+            existingNode.setNext( newNode );
+            newNode.setPrevious( existingNode );
+            this.lastNode = newNode;
+        } else {
+            (existingNode.getNext()).setPrevious( newNode );
+            newNode.setNext( existingNode.getNext() );
+            existingNode.setNext( newNode );
+            newNode.setPrevious( existingNode );
+        }
+        this.size++;
+    }
+
+    /**
+     * Remove the last node from the list. The previous node then becomes the last node. If this is the last 
+     * node then both first and last node references are set to null.
+     * 
+     * @return
+     *      The first <code>LinkedListNode</code>.
+     */
+    public LinkedListNode removeLast() {
+        if ( this.lastNode == null ) {
+            return null;
+        }
+        final LinkedListNode node = this.lastNode;
+        this.lastNode = node.getPrevious();
+        node.setPrevious( null );
+        if ( this.lastNode != null ) {
+            this.lastNode.setNext( null );
+        } else {
+            this.firstNode = this.lastNode;
+        }
+        this.size--;
+        return node;
+    }
+
+    /**
+     * @return
+     *      boolean value indicating the empty status of the list
+     */
+    public final boolean isEmpty() {
+        return (this.firstNode == null);
+    }
+
+    /**
+     * Iterates the list removing all the nodes until there are no more nodes to remove. 
+     */
+    public void clear() {
+        while ( removeFirst() != null ) {
+        }
+    }
+
+    /**
+     * @return
+     *     return size of the list as an int
+     */
+    public final int size() {
+        return this.size;
+    }
+
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        for ( LinkedListNode node = this.firstNode; node != null; node = node.getNext() ) {
+            result = PRIME * result + node.hashCode();
+        }
+        return result;
+    }
+
+    public boolean equals(final Object object) {
+        if ( object == this ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof LinkedList) ) {
+            return false;
+        }
+
+        final LinkedList other = (LinkedList) object;
+
+        if ( this.size() != other.size() ) {
+            return false;
+        }
+
+        for ( LinkedListNode thisNode = this.firstNode, otherNode = other.firstNode; thisNode != null && otherNode != null; thisNode = thisNode.getNext(), otherNode = otherNode.getNext() ) {
+            if ( !thisNode.equals( otherNode ) ) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public Iterator iterator() {
+        this.iterator.reset( this );
+        return this.iterator;
+    }
+
+    public java.util.Iterator javaUtilIterator() {
+        return new JavaUtilIterator( this );
+    }
+
+    /**
+     * Returns a list iterator
+     * @return
+     */
+    public class LinkedListIterator
+        implements
+        Iterator,
+        Serializable {
+        private LinkedList     list;
+        private LinkedListNode current;
+
+        public void reset(final LinkedList list) {
+            this.list = list;
+            this.current = this.list.firstNode;
+        }
+
+        public Object next() {
+            if ( this.current == null ) {
+                return null;
+            }
+            final LinkedListNode node = this.current;
+            this.current = this.current.getNext();
+            return node;
+        }
+    }
+
+    public static class JavaUtilIterator
+        implements
+        java.util.Iterator,
+        Serializable {
+        private LinkedList     list;
+        private LinkedListNode currentNode;
+        private LinkedListNode nextNode;
+        private boolean        immutable;
+
+        public JavaUtilIterator(final LinkedList list) {
+            this( list,
+                  true );
+        }
+
+        public JavaUtilIterator(final LinkedList list,
+                                final boolean immutable) {
+            this.list = list;
+            this.nextNode = this.list.getFirst();
+            this.immutable = immutable;
+        }
+
+        public boolean hasNext() {
+            return (this.nextNode != null);
+        }
+
+        public Object next() {
+            this.currentNode = this.nextNode;
+            if ( this.currentNode != null ) {
+                this.nextNode = this.currentNode.getNext();
+            } else {
+                throw new NoSuchElementException( "No more elements to return" );
+            }
+            return this.currentNode;
+        }
+
+        public void remove() {
+            if ( this.immutable ) {
+                throw new UnsupportedOperationException( "This  Iterator is immutable, you cannot call remove()" );
+            }
+
+            if ( this.currentNode != null ) {
+                this.list.remove( this.currentNode );
+                this.currentNode = null;
+            } else {
+                throw new IllegalStateException( "No item to remove. Call next() before calling remove()." );
+            }
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/LinkedListEntry.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/LinkedListEntry.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/LinkedListEntry.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,44 @@
+package org.drools.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * The idea behind <code>LinkedListNodeWrapper</code> is to be able to add
+ * the same <code>LinkedListNode</code> to multiple <code>LinkedList</code>s 
+ * where the node can have different previous and next nodes in each list.
+ */
+public class LinkedListEntry extends AbstractBaseLinkedListNode {
+
+    private static final long serialVersionUID = 400L;
+    private Object            object;
+
+    public LinkedListEntry(final Object object) {
+        this.object = object;
+    }
+
+    public Object getObject() {
+        return this.object;
+    }
+
+    public int hashCode() {
+        return this.object.hashCode();
+    }
+
+    public boolean equals(final Object other) {
+        return this.object.equals( other );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/LinkedListNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/LinkedListNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/LinkedListNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,61 @@
+package org.drools.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+/**
+ * Items placed in a <code>LinkedList<code> must implement this interface .
+ * 
+ * @see LinkedList
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ */
+public interface LinkedListNode
+    extends
+    Serializable {
+
+    /**
+     * Returns the next node
+     * @return
+     *      The next LinkedListNode
+     */
+    public LinkedListNode getNext();
+
+    /**
+     * Sets the next node 
+     * @param next
+     *      The next LinkedListNode
+     */
+    public void setNext(LinkedListNode next);
+
+    /**
+     * Returns the previous node
+     * @return
+     *      The previous LinkedListNode
+     */
+    public LinkedListNode getPrevious();
+
+    /**
+     * Sets the previous node 
+     * @param previous
+     *      The previous LinkedListNode
+     */
+    public void setPrevious(LinkedListNode previous);
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ObjectHashMap.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ObjectHashMap.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ObjectHashMap.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,182 @@
+/**
+ * 
+ */
+package org.drools.util;
+
+import org.drools.util.AbstractHashTable.EqualityEquals;
+
+public class ObjectHashMap extends AbstractHashTable {
+
+    private static final long serialVersionUID = 400L;
+
+    public ObjectHashMap() {
+        this( 16,
+              0.75f );
+    }
+
+    public ObjectHashMap(final int capacity,
+                         final float loadFactor) {
+        super( capacity,
+               loadFactor );
+    }
+    
+    public ObjectHashMap(final Entry[] table) {
+        super( 0.75f, table);
+    }      
+    
+    public ObjectHashMap(final float loadFactor,
+                             final Entry[] table) {
+        super(loadFactor, table);
+    }     
+
+    public Object put(final Object key,
+                      final Object value) {
+        return put( key,
+                    value,
+                    true );
+    }
+
+    public void clear() {
+        this.table = new Entry[Math.min( this.table.length,
+                                         16 )];
+        this.threshold = (int) (this.table.length * this.loadFactor);
+    }
+
+    public Object put(final Object key,
+                      final Object value,
+                      final boolean checkExists) {
+        final int hashCode = this.comparator.hashCodeOf( key );
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+
+        // scan the linked entries to see if it exists
+        if ( checkExists ) {
+            ObjectEntry current = (ObjectEntry) this.table[index];
+            while ( current != null ) {
+                if ( hashCode == current.hashCode && this.comparator.equal( key,
+                                                                            current.key ) ) {
+                    final Object oldValue = current.value;
+                    current.value = value;
+                    return oldValue;
+                }
+                current = (ObjectEntry) current.getNext();
+            }
+        }
+
+        // We aren't checking the key exists, or it didn't find the key
+        final ObjectEntry entry = new ObjectEntry( key,
+                                                   value,
+                                                   hashCode );
+        entry.next = this.table[index];
+        this.table[index] = entry;
+
+        if ( this.size++ >= this.threshold ) {
+            resize( 2 * this.table.length );
+        }
+        return null;
+    }
+
+    public Object get(final Object key) {
+        final int hashCode = this.comparator.hashCodeOf( key );
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+
+        ObjectEntry current = (ObjectEntry) this.table[index];
+        while ( current != null ) {
+            if ( hashCode == current.hashCode && this.comparator.equal( key,
+                                                                        current.key ) ) {
+                return current.value;
+            }
+            current = (ObjectEntry) current.getNext();
+        }
+        return null;
+    }
+
+    public Object remove(final Object key) {
+        final int hashCode = this.comparator.hashCodeOf( key );
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+
+        ObjectEntry previous = (ObjectEntry) this.table[index];
+        ObjectEntry current = previous;
+        while ( current != null ) {
+            final ObjectEntry next = (ObjectEntry) current.getNext();
+            if ( hashCode == current.hashCode && this.comparator.equal( key,
+                                                                        current.key ) ) {
+                if ( previous == current ) {
+                    this.table[index] = next;
+                } else {
+                    previous.setNext( next );
+                }
+                current.setNext( null );
+                this.size--;
+                return current.value;
+            }
+            previous = current;
+            current = next;
+        }
+        return null;
+    }
+
+    public Entry getBucket(final Object object) {
+        final int hashCode = this.comparator.hashCodeOf( object );
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+
+        return this.table[index];
+    }
+
+    public static class ObjectEntry
+        implements
+        Entry {
+
+        private static final long serialVersionUID = 400L;
+
+        private Object            key;
+
+        private Object            value;
+
+        private int               hashCode;
+
+        private Entry             next;
+
+        public ObjectEntry(final Object key,
+                           final Object value,
+                           final int hashCode) {
+            this.key = key;
+            this.value = value;
+            this.hashCode = hashCode;
+        }
+
+        public Object getValue() {
+            return this.value;
+        }
+
+        public Object getKey() {
+            return this.key;
+        }
+
+        public Entry getNext() {
+            return this.next;
+        }
+
+        public void setNext(final Entry next) {
+            this.next = next;
+        }
+
+        public int hashCode() {
+            return this.hashCode;
+        }
+
+        public boolean equals(final Object object) {
+            if ( object == this ) {
+                return true;
+            }
+
+            // assumes we never have null or wrong class
+
+            final ObjectEntry other = (ObjectEntry) object;
+            return this.key.equals( other.key ) && this.value.equals( other.value );
+        }
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ObjectHashSet.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ObjectHashSet.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ObjectHashSet.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,181 @@
+/**
+ * 
+ */
+package org.drools.util;
+
+import org.drools.util.AbstractHashTable.EqualityEquals;
+
+public class ObjectHashSet extends AbstractHashTable {
+
+    private static final long serialVersionUID = 400L;
+
+    public ObjectHashSet() {
+        this( 16,
+              0.75f );
+    }
+
+    public ObjectHashSet(final int capacity,
+                         final float loadFactor) {
+        super( capacity,
+               loadFactor );
+    }
+
+    public ObjectHashSet(final Entry[] table) {
+        super( 0.75f,
+               table );
+    }
+
+    public ObjectHashSet(final float loadFactor,
+                         final Entry[] table) {
+        super( loadFactor,
+               table );
+    }
+
+    public boolean add(final Object value) {
+        return add( value,
+                    true );
+    }
+
+    public void clear() {
+        this.table = new Entry[Math.min( this.table.length,
+                                         16 )];
+        this.threshold = (int) (this.table.length * this.loadFactor);
+    }
+
+    public boolean add(final Object value,
+                       final boolean checkExists) {
+        final int hashCode = this.comparator.hashCodeOf( value );
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+
+        // scan the linked entries to see if it exists
+        if ( checkExists ) {
+            ObjectEntry current = (ObjectEntry) this.table[index];
+            while ( current != null ) {
+                if ( hashCode == current.hashCode && this.comparator.equal( value,
+                                                                            current.value ) ) {
+                    final Object oldValue = current.value;
+                    current.value = value;
+                    return true;
+                }
+                current = (ObjectEntry) current.getNext();
+            }
+        }
+
+        // We aren't checking the key exists, or it didn't find the key
+        final ObjectEntry entry = new ObjectEntry( value,
+                                                   hashCode );
+        entry.next = this.table[index];
+        this.table[index] = entry;
+
+        if ( this.size++ >= this.threshold ) {
+            resize( 2 * this.table.length );
+        }
+        return false;
+    }
+
+    public boolean contains(final Object value) {
+        final int hashCode = this.comparator.hashCodeOf( value );
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+
+        ObjectEntry current = (ObjectEntry) this.table[index];
+        while ( current != null ) {
+            if ( hashCode == current.hashCode && this.comparator.equal( value,
+                                                                        current.value ) ) {
+                return true;
+            }
+            current = (ObjectEntry) current.getNext();
+        }
+        return false;
+    }
+
+    public boolean remove(final Object value) {
+        final int hashCode = this.comparator.hashCodeOf( value );
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+
+        ObjectEntry previous = (ObjectEntry) this.table[index];
+        ObjectEntry current = previous;
+        while ( current != null ) {
+            final ObjectEntry next = (ObjectEntry) current.getNext();
+            if ( hashCode == current.hashCode && this.comparator.equal( value,
+                                                                        current.value ) ) {
+                if ( previous == current ) {
+                    this.table[index] = next;
+                } else {
+                    previous.setNext( next );
+                }
+                current.setNext( null );
+                this.size--;
+                return true;
+            }
+            previous = current;
+            current = next;
+        }
+        return false;
+    }
+
+    public Entry getBucket(final Object object) {
+        final int hashCode = this.comparator.hashCodeOf( object );
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+
+        return this.table[index];
+    }
+    
+    public Object[] toArray(Object[] objects) {
+        Iterator it = iterator();
+        int i = 0;
+        for ( ObjectEntry entry = ( ObjectEntry) it.next(); entry != null; entry = ( ObjectEntry ) it.next() ) {
+            objects[i++] = entry.getValue();
+        }
+        return objects;
+    }
+
+    public static class ObjectEntry
+        implements
+        Entry {
+
+        private static final long serialVersionUID = 400L;
+
+        private Object            value;
+
+        private int               hashCode;
+
+        private Entry             next;
+
+        public ObjectEntry(final Object value,
+                           final int hashCode) {
+            this.value = value;
+            this.hashCode = hashCode;
+        }
+
+        public Object getValue() {
+            return this.value;
+        }
+
+        public Entry getNext() {
+            return this.next;
+        }
+
+        public void setNext(final Entry next) {
+            this.next = next;
+        }
+
+        public int hashCode() {
+            return this.hashCode;
+        }
+
+        public boolean equals(final Object object) {
+            if ( object == this ) {
+                return true;
+            }
+
+            // assumes we never have null or wrong class
+
+            final ObjectEntry other = (ObjectEntry) object;
+            return this.value.equals( other.value );
+        }
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/OrderedFactHashTable.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/OrderedFactHashTable.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/OrderedFactHashTable.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,79 @@
+package org.drools.util;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedList;
+
+import org.drools.common.EventFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.spi.PropagationContext;
+
+public class OrderedFactHashTable extends FactHashTable {
+
+	private static final long serialVersionUID = 5831401733699912996L;
+	
+	LinkedList<EventFactHandle> orderedEventList;
+	
+	public OrderedFactHashTable() {
+		orderedEventList = new LinkedList<EventFactHandle>();
+	}
+
+	public OrderedFactHashTable(int capacity, float loadFactor) {
+		super(capacity, loadFactor);
+		orderedEventList = new LinkedList<EventFactHandle>();
+	}
+
+	public boolean add(final InternalFactHandle handle) {
+        boolean returnValue = super.add(handle);
+        if (handle.isEvent()){
+        		 EventFactHandle evHandle = (EventFactHandle)handle;
+    	    	 int index = Collections.binarySearch(orderedEventList, evHandle, new EventFactHandleComparator());
+    	    	 // Add the item to the list; 
+    	    	 // if non-existent, i.e. scheduledTime does not exist yet, index will be < 0; then, insert at position -index-1
+    	    	 // if scheduledTime exists, index will be >= 0; then, insert at position index+1
+    	    	 orderedEventList.add(Math.abs(-index-1), evHandle);
+    	     }
+        return returnValue;
+    }
+	
+	public boolean remove(final InternalFactHandle handle) {
+       boolean returnValue = super.remove(handle);
+       if (returnValue != false)
+    	   orderedEventList.remove(handle);
+       return returnValue;
+    }
+	
+	public boolean remove() {
+		// makes sure to not remove the initial fact
+		InternalFactHandle removedHandle = orderedEventList.poll();
+		if (removedHandle != null){
+			super.remove(removedHandle);
+	    	return true;
+		}
+		return false;
+	}
+	
+	public java.util.Iterator<EventFactHandle> orderedEventFactHandleIterator() {
+		return orderedEventList.iterator();
+	}
+	
+	public InternalFactHandle peek(){
+		return orderedEventList.peek();
+	}
+	
+	private class EventFactHandleComparator  
+		implements Comparator<EventFactHandle>{
+
+		@Override
+		public int compare(EventFactHandle fh1, EventFactHandle fh2) {
+			long t1 = fh1.getEndTimestamp(); 
+			long t2 = fh2.getEndTimestamp();
+			if (t1 < t2)
+				return -1;
+			else if (t1 > t2)
+				return 1;
+			else return 0;
+		}
+	
+	}
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/OrderedTupleHashTable.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/OrderedTupleHashTable.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/OrderedTupleHashTable.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,75 @@
+package org.drools.util;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedList;
+
+import org.drools.reteoo.ReteTuple;
+
+public class OrderedTupleHashTable extends TupleHashTable {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1004326464723176484L;
+	
+	LinkedList<ReteTuple> orderedTupleList;
+	
+	public OrderedTupleHashTable() {
+		orderedTupleList = new LinkedList<ReteTuple>();
+	}
+
+	public OrderedTupleHashTable(int capacity, float loadFactor) {
+		super(capacity, loadFactor);
+		orderedTupleList = new LinkedList<ReteTuple>();
+	}
+	
+	public void add(final ReteTuple tuple) {
+		 super.add(tuple);
+	     if (tuple.containsEvents()){
+	    	 int index = Collections.binarySearch(orderedTupleList, tuple, new TupleComparator());
+	    	 // Add the item to the list
+	    	 // if non-existent, i.e. scheduledTime does not exist yet, index will be < 0; then, insert at position -index-1
+	    	 // if scheduledTime exists, index will be >= 0; then, insert at position index+1
+	    	 orderedTupleList.add(Math.abs(-index-1), tuple);
+	    	 //if (index < 0) 
+	    	 //	 orderedTupleList.add(-index-1, tuple);
+	    	 //System.out.println ("\nInsert tuple "+ tuple.toString() +" at " + Math.abs(-index-1) + " position.");
+	     }
+    }
+	
+	public ReteTuple remove(final ReteTuple tuple) {
+       ReteTuple removedTuple = super.remove(tuple);
+       if (removedTuple != null)
+    	   orderedTupleList.remove(tuple);
+       return removedTuple;
+    }
+	
+	public ReteTuple remove() {
+		// makes sure to not remove the initialFact tuple
+		ReteTuple removedTuple = orderedTupleList.poll();
+		if (removedTuple != null)
+			super.remove(removedTuple);
+	    return removedTuple;
+	}
+
+	public ReteTuple peek(){
+		return orderedTupleList.peek();
+	}
+	
+	private class TupleComparator  
+		implements Comparator<ReteTuple>{
+
+		@Override
+		public int compare(ReteTuple tuple1, ReteTuple tuple2) {
+			long t1 = tuple1.getCreationTimeFirstContributingEvent(); 
+			long t2 = tuple2.getCreationTimeFirstContributingEvent();
+			if (t1 < t2)
+				return -1;
+			else if (t1 > t2)
+				return 1;
+			else return 0;
+		}
+		
+	}
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/PrimitiveLongMap.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/PrimitiveLongMap.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/PrimitiveLongMap.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,471 @@
+package org.drools.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Collection;
+
+/**
+ * 
+ * @author Mark Proctor
+ */
+public class PrimitiveLongMap
+    implements
+    Serializable {
+    /**
+     * 
+     */
+    private static final long   serialVersionUID = 400L;
+
+    private final static Object NULL             = new Serializable() {
+
+                                                     /**
+                                                      * 
+                                                      */
+                                                     private static final long serialVersionUID = 400L;
+                                                 };
+
+    private final int           indexIntervals;
+    private final int           intervalShifts;
+    private final int           midIntervalPoint;
+    private final int           tableSize;
+    private final int           shifts;
+    private final int           doubleShifts;
+    private Page                firstPage;
+    private Page                lastPage;
+    private int                 lastPageId;
+    private long                maxKey;
+    private Page[]              pageIndex;
+    private int                 totalSize;
+
+    public PrimitiveLongMap() {
+        this( 32,
+              8 );
+    }
+
+    public PrimitiveLongMap(final int tableSize) {
+        this( tableSize,
+              8 );
+    }
+
+    public PrimitiveLongMap(final int tableSize,
+                            final int indexIntervals) {
+        // determine number of shifts for intervals
+        int i = 1;
+        int size = 2;
+        while ( size < indexIntervals ) {
+            size <<= 1;
+            ++i;
+        }
+        this.indexIntervals = size;
+        this.intervalShifts = i;
+
+        // determine number of shifts for tableSize
+        i = 1;
+        size = 2;
+        while ( size < tableSize ) {
+            size <<= 1;
+            ++i;
+        }
+        this.tableSize = size;
+        this.shifts = i;
+        this.doubleShifts = this.shifts << 1;
+
+        // determine mid point of an interval
+        this.midIntervalPoint = ((this.tableSize << this.shifts) << this.intervalShifts) >> 1;
+
+        this.lastPageId = 0;
+
+        init();
+    }
+
+    private void init() {
+        // instantiate the first page
+        // previous sibling of first page is null
+        // next sibling of last page is null
+        this.firstPage = new Page( null,
+                                   this.lastPageId,
+                                   this.tableSize );
+        this.maxKey = this.lastPageId + 1 << this.doubleShifts;
+        // create an index of one
+        this.pageIndex = new Page[]{this.firstPage};
+
+        // our first page is also our last page
+        this.lastPage = this.firstPage;
+    }
+
+    public void clear() {
+        init();
+    }
+
+    public boolean isEmpty() {
+        return this.totalSize == 0;
+    }
+
+    public Object put(final long key,
+                      Object value) {
+        if ( key < 0 ) {
+            throw new IllegalArgumentException( "-ve keys not supported: " + key );
+        }
+
+        // NULL is a placeholder to show the key exists
+        // but contains a null value
+        if ( value == null ) {
+            value = PrimitiveLongMap.NULL;
+        }
+
+        final Page page = findPage( key );
+
+        final Object oldValue = page.put( key,
+                                          value );
+
+        if ( oldValue == null ) {
+            this.totalSize++;
+        }
+
+        return oldValue;
+    }
+
+    public Object remove(final long key) {
+        if ( key > this.maxKey || key < 0 ) {
+            return null;
+        }
+
+        final Page page = findPage( key );
+
+        final Object oldValue = page.put( key,
+                                          null );
+
+        if ( this.lastPageId != 0 && this.lastPage.isEmpty() ) {
+            shrinkPages( this.lastPageId );
+        }
+
+        if ( oldValue != null ) {
+            this.totalSize--;
+        }
+
+        return oldValue;
+    }
+
+    public Object get(final long key) {
+        if ( key > this.maxKey || key < 0 ) {
+            return null;
+        }
+
+        Object value = findPage( key ).get( key );
+
+        // NULL means the key exists, so return a real null
+        if ( value == PrimitiveLongMap.NULL ) {
+            value = null;
+        }
+        return value;
+    }
+    
+    /**
+     * gets the next populated key, after the given key position.
+     * @param key
+     * @return
+     */
+    public long getNext(long key) {
+        final int currentPageId = (int) key >> this.doubleShifts;
+        final int nextPageId = (int) (key+1) >> this.doubleShifts;
+        
+        if ( currentPageId != nextPageId ) {
+            Page page = findPage( key + 1);
+            while ( page.isEmpty() ) {
+                page = page.getNextSibling();
+            }
+            key = this.doubleShifts << page.getPageId();
+        } else {
+            key += 1;
+        }
+        
+        while ( !containsKey( key ) && key <= this.maxKey ) {
+            key++;
+        }
+        
+        if ( key > this.maxKey ) {
+            key -= 1;
+        }
+                                
+        return key;
+    }
+
+    public int size() {
+        return this.totalSize;
+    }
+
+    public Collection values() {
+        final CompositeCollection collection = new CompositeCollection();
+        Page page = this.firstPage;
+
+        while ( page != null && page.getPageId() <= this.lastPageId ) {
+            collection.addComposited( Arrays.asList( page.getValues() ) );
+            page = page.getNextSibling();
+        }
+        return collection;
+    }
+
+    public boolean containsKey(final long key) {
+        if ( key < 0 ) {
+            return false;
+        }
+
+        return get( key ) != null;
+    }
+
+    /**
+     * Expand index to accomodate given pageId Create empty TopNodes
+     */
+    public Page expandPages(final int toPageId) {
+        for ( int x = this.lastPageId; x < toPageId; x++ ) {
+            this.lastPage = new Page( this.lastPage,
+                                      ++this.lastPageId,
+                                      this.tableSize );
+            // index interval, so expand index
+            if ( this.lastPage.getPageId() % this.indexIntervals == 0 ) {
+                final int newSize = this.pageIndex.length + 1;
+                resizeIndex( newSize );
+                this.pageIndex[newSize - 1] = this.lastPage;
+            }
+        }
+        this.maxKey = (this.lastPageId + 1 << this.doubleShifts) - 1;
+        return this.lastPage;
+    }
+
+    /**
+     * Shrink index to accomodate given pageId
+     */
+    public void shrinkPages(final int toPageId) {
+        for ( int x = this.lastPageId; x >= toPageId; x-- ) {
+            // last page is on index so shrink index
+            if ( (this.lastPageId) % this.indexIntervals == 0 && this.lastPageId != 0 ) {
+                resizeIndex( this.pageIndex.length - 1 );
+            }
+
+            final Page page = this.lastPage.getPreviousSibling();
+            page.setNextSibling( null );
+            this.lastPage.clear();
+            this.lastPage = page;
+            this.lastPageId = page.getPageId();
+
+        }
+    }
+
+    public void resizeIndex(final int newSize) {
+        final Page[] newIndex = new Page[newSize];
+        System.arraycopy( this.pageIndex,
+                          0,
+                          newIndex,
+                          0,
+                          (newSize > this.pageIndex.length) ? this.pageIndex.length : newSize );
+        this.pageIndex = newIndex;
+    }
+
+    private Page findPage(final long key) {
+        // determine Page
+        final int pageId = (int) key >> this.doubleShifts;
+        Page page;
+
+        // if pageId is lastNodeId use lastNode reference
+        if ( pageId == this.lastPageId ) {
+            page = this.lastPage;
+        }
+        // if pageId is zero use first page reference
+        else if ( pageId == 0 ) {
+            page = this.firstPage;
+        }
+        // if pageId is greater than lastTopNodeId need to expand
+        else if ( pageId > this.lastPageId ) {
+            page = expandPages( pageId );
+        } else {
+            // determine offset
+            final int offset = pageId >> this.intervalShifts;
+            // are we before or after the halfway point of an index interval
+            if ( (offset != (this.pageIndex.length - 1)) && ((key - (offset << this.intervalShifts << this.doubleShifts)) > this.midIntervalPoint) ) {
+                // after so go to next node index and go backwards
+                page = this.pageIndex[offset + 1];
+                while ( page.getPageId() != pageId ) {
+                    page = page.getPreviousSibling();
+                }
+            } else {
+                // before so go to node index and go forwards
+                page = this.pageIndex[offset];
+                while ( page.getPageId() != pageId ) {
+                    page = page.getNextSibling();
+                }
+            }
+        }
+
+        return page;
+    }
+
+    private static class Page
+        implements
+        Serializable {
+        /**
+         * 
+         */
+        private static final long serialVersionUID = 400L;
+        private final int         pageSize;
+        private final int         pageId;
+        private final int         shifts;
+        private final int         tableSize;
+        private Page              nextSibling;
+        private Page              previousSibling;
+        private Object[][]        tables;
+        private int               filledSlots;
+
+        Page(final Page previousSibling,
+             final int pageId,
+             final int tableSize) {
+            // determine number of shifts
+            int i = 1;
+            int size = 2;
+            while ( size < tableSize ) {
+                size <<= 1;
+                ++i;
+            }
+            // make sure table size is valid
+            this.tableSize = size;
+            this.shifts = i;
+
+            // create bi-directional link
+            this.previousSibling = previousSibling;
+            if ( this.previousSibling != null ) {
+                this.previousSibling.setNextSibling( this );
+            }
+            this.pageId = pageId;
+            this.pageSize = tableSize << this.shifts;
+        }
+
+        public int getPageId() {
+            return this.pageId;
+        }
+
+        void setNextSibling(final Page nextSibling) {
+            this.nextSibling = nextSibling;
+        }
+
+        public Page getNextSibling() {
+            return this.nextSibling;
+        }
+
+        void setPreviousSibling(final Page previousSibling) {
+            this.previousSibling = previousSibling;
+        }
+
+        public Page getPreviousSibling() {
+            return this.previousSibling;
+        }
+
+        public Object get(long key) {
+            if ( this.tables == null ) {
+                return null;
+            }
+            // normalise key
+            key -= this.pageSize * this.pageId;
+
+            // determine table
+            final int table = (int) key >> this.shifts;
+
+            // determine offset
+            final int offset = table << this.shifts;
+
+            // tables[table][slot]
+            return this.tables[table][(int) key - offset];
+        }              
+
+        public Object put(long key,
+                          final Object newValue) {
+            if ( this.tables == null ) {
+                // initiate tree;
+                this.tables = new Object[this.tableSize][this.tableSize];
+            }
+
+            // normalise key
+            key -= this.pageSize * this.pageId;
+
+            // determine table
+            final int table = (int) key >> this.shifts;
+
+            // determine offset
+            final int offset = table << this.shifts;
+
+            // determine slot
+            final int slot = (int) key - offset;
+
+            // get old value
+            final Object oldValue = this.tables[table][slot];
+            this.tables[table][slot] = newValue;
+
+            // update number of empty cells for TopNode
+            if ( oldValue == null && newValue != null ) {
+                this.filledSlots++;
+            } else if ( oldValue != null && newValue == null ) {
+                this.filledSlots--;
+            }
+
+            // if this page contains no values then null the array
+            // to allow it to be garbage collected
+            if ( this.filledSlots == 0 ) {
+                this.tables = null;
+            }
+
+            return oldValue;
+        }
+
+        Object[][] getTables() {
+            return this.tables;
+        }
+
+        Object[] getValues() {
+            final Object[] values = new Object[this.filledSlots];
+            if ( values.length == 0 ) {
+                return values;
+            }
+            int x = 0;
+            Object value;
+            for ( int i = 0; i < this.tableSize; i++ ) {
+                for ( int j = 0; j < this.tableSize; j++ ) {
+                    value = this.tables[i][j];
+                    if ( value != null ) {
+                        // swap NULL out placeholder
+                        // Also filter out InitialFact
+                        if ( value == PrimitiveLongMap.NULL ) {
+                            value = null;
+                        }
+                        values[x] = value;
+                        x++;
+                    }
+                }
+            }
+            return values;
+        }
+
+        public boolean isEmpty() {
+            return this.filledSlots == 0;
+        }
+
+        void clear() {
+            this.previousSibling = null;
+            this.nextSibling = null;
+            this.tables = null;
+        }
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/PrimitiveLongStack.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/PrimitiveLongStack.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/PrimitiveLongStack.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,142 @@
+package org.drools.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+public class PrimitiveLongStack
+    implements
+    Serializable {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+    private final int         tableSize;
+    private int               currentPageId;
+    private Page              currentPage;
+
+    public PrimitiveLongStack() {
+        this( 256 );
+    }
+
+    public PrimitiveLongStack(final int tableSize) {
+        this.tableSize = tableSize;
+        this.currentPageId = 0;
+
+        // instantiate the first node
+        // previous sibling of first node is null
+        // next sibling of last node is null
+        this.currentPage = new Page( null,
+                                     this.currentPageId,
+                                     this.tableSize );
+    }
+
+    public void push(final long value) {
+        if ( this.currentPage.getPosition() == this.tableSize - 1 ) {
+
+            final Page node = new Page( this.currentPage,
+                                        ++this.currentPageId,
+                                        this.tableSize );
+            this.currentPage = node;
+        }
+
+        this.currentPage.push( value );
+    }
+
+    public long pop() {
+        if ( this.currentPage.getPosition() == -1 ) {
+            if ( this.currentPageId == 0 ) {
+                throw new RuntimeException( "Unable to pop" );
+            }
+
+            final Page node = this.currentPage;
+            this.currentPage = node.getPreviousSibling();
+            this.currentPageId--;
+            node.remove();
+
+        }
+
+        return this.currentPage.pop();
+    }
+
+    public boolean isEmpty() {
+        return this.currentPageId == 0 && this.currentPage.getPosition() == -1;
+    }
+
+    private static final class Page
+        implements
+        Serializable {
+        /**
+         * 
+         */
+        private static final long serialVersionUID = 400L;
+        private final int         pageId;
+        private Page              nextSibling;
+        private Page              previousSibling;
+        private long[]            table;
+        private int               lastKey;
+
+        Page(final Page previousSibling,
+             final int nodeId,
+             final int tableSize) {
+            // create bi-directional link
+            this.previousSibling = previousSibling;
+            if ( this.previousSibling != null ) {
+                this.previousSibling.setNextSibling( this );
+            }
+            this.pageId = nodeId;
+            this.lastKey = -1;
+
+            // initiate tree;
+            this.table = new long[tableSize];
+        }
+
+        public int getNodeId() {
+            return this.pageId;
+        }
+
+        void setNextSibling(final Page nextSibling) {
+            this.nextSibling = nextSibling;
+        }
+
+        public Page getNextSibling() {
+            return this.nextSibling;
+        }
+
+        public Page getPreviousSibling() {
+            return this.previousSibling;
+        }
+
+        public long pop() {
+            return this.table[this.lastKey--];
+        }
+
+        public void push(final long value) {
+            this.table[++this.lastKey] = value;
+        }
+
+        public int getPosition() {
+            return this.lastKey;
+        }
+
+        void remove() {
+            this.previousSibling.setNextSibling( null );
+            this.previousSibling = null;
+            this.table = null;
+        }
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/Queue.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/Queue.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/Queue.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,27 @@
+package org.drools.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public interface Queue {
+    public void enqueue(Queueable queueable);
+
+    public Queueable dequeue();
+
+    public Queueable dequeue(int index);
+
+    public boolean isEmpty();
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/Queueable.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/Queueable.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/Queueable.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,26 @@
+package org.drools.util;
+
+import org.drools.spi.Activation;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public interface Queueable extends Activation {
+    public void enqueued(Queue queue,
+                         int index);
+
+    public void dequeue();
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ReflectiveVisitor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ReflectiveVisitor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ReflectiveVisitor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,102 @@
+package org.drools.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.Method;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.Visitor;
+
+/**
+ * Java Tip 98: Reflect on the Visitor design pattern. Implement visitors in
+ * Java, using reflection.
+ * http://www.javaworld.com/javaworld/javatips/jw-javatip98.html
+ * 
+ * @author Jeremy Blosser
+ */
+public abstract class ReflectiveVisitor
+    implements
+    Visitor {
+    static final String newline = System.getProperty( "line.separator" );
+
+    public void visit(final Object object) {
+        Method method = null;
+        try {
+            if ( object != null ) {
+                method = getMethod( object.getClass() );
+                method.invoke( this,
+                               new Object[]{object} );
+            } else {
+                method = getClass().getMethod( "visitNull",
+                                               (Class[]) null );
+                method.invoke( this,
+                               (Object[]) null );
+            }
+        } catch ( final Exception e ) {
+            throw new RuntimeDroolsException( e.toString() + " : " + object,
+                                              e.getCause() );
+        }
+    }
+
+    private Method getMethod(final Class clazz) {
+        Class newClazz = clazz;
+        Method method = null;
+
+        // Try the superclasses
+        while ( method == null && newClazz != Object.class ) {
+            String methodName = newClazz.getName();
+            methodName = "visit" + methodName.substring( methodName.lastIndexOf( '.' ) + 1 );
+            try {
+                method = getClass().getMethod( methodName,
+                                               new Class[]{newClazz} );
+            } catch ( final NoSuchMethodException e ) {
+                newClazz = newClazz.getSuperclass();
+            }
+        }
+
+        // Try the interfaces.
+        if ( newClazz == Object.class ) {
+            final Class[] interfaces = clazz.getInterfaces();
+            for ( int i = 0; i < interfaces.length; i++ ) {
+                String methodName = interfaces[i].getName();
+                methodName = "visit" + methodName.substring( methodName.lastIndexOf( '.' ) + 1 );
+                try {
+                    method = getClass().getMethod( methodName,
+                                                   new Class[]{interfaces[i]} );
+                } catch ( final NoSuchMethodException e ) {
+                    // swallow
+                }
+            }
+        }
+        if ( method == null ) {
+            try {
+                method = getClass().getMethod( "visitObject",
+                                               new Class[]{Object.class} );
+            } catch ( final Exception e ) {
+                // Shouldn't happen as long as all Visitors extend this class
+                // and this class continues to implement visitObject(Object).
+                throw new RuntimeDroolsException( e.toString() + " : " + clazz,
+                                                  e.getCause() );
+            }
+        }
+        return method;
+    }
+
+    public void visitObject(final Object object) {
+        System.err.println( "no visitor implementation for : " + object.getClass() + " : " + object );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ShadowProxyUtils.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ShadowProxyUtils.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ShadowProxyUtils.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Jul 5, 2007
+ */
+package org.drools.util;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.drools.base.ShadowProxy;
+
+/**
+ * A class with simple utility methods for shadowing
+ * 
+ * @author etirelli
+ */
+public class ShadowProxyUtils {
+
+    /* Collections.UnmodifiableCollection is a package
+     * private class, thus the confusing bit above
+     * to get a Class to compare to. */
+    private static final Class UNMODIFIABLE_MAP        = Collections.unmodifiableMap( Collections.EMPTY_MAP ).getClass();
+    private static final Class UNMODIFIABLE_COLLECTION = Collections.unmodifiableCollection( Collections.EMPTY_LIST ).getClass();
+
+    private ShadowProxyUtils() {
+    }
+
+    public static Object cloneObject(Object original) {
+        Object clone = null;
+        if ( original instanceof Cloneable ) {
+            try {
+                Method cloneMethod = original.getClass().getMethod( "clone",
+                                                                    new Class[0] );
+                clone = cloneMethod.invoke( original,
+                                            new Object[0] );
+            } catch ( Exception e ) {
+                /* Failed to clone.  Don't worry about it, and just return
+                 * the original object. */
+            }
+        }
+
+        if ( clone == null ) {
+            try {
+                if ( original instanceof Map && 
+                     original != Collections.EMPTY_MAP && 
+                     !UNMODIFIABLE_MAP.isAssignableFrom( original.getClass() ) ) {
+                    
+                    /* empty and unmodifiable maps can't (and don't need to) be shadowed */
+                    clone = original.getClass().newInstance();
+                    ((Map) clone).putAll( (Map) original );
+                    
+                } else if ( original instanceof Collection && 
+                            original != Collections.EMPTY_LIST && 
+                            original != Collections.EMPTY_SET && 
+                            !UNMODIFIABLE_COLLECTION.isAssignableFrom( original.getClass() ) ) {
+                    
+                    /* empty and unmodifiable collections can't (and don't need to) be shadowed */
+                    clone = original.getClass().newInstance();
+                    ((Collection) clone).addAll( (Collection) original );
+                    
+                } else if ( original.getClass().isArray() ) {
+                    clone = cloneArray( original );
+                }
+                
+            } catch ( Exception e ) {
+                /* Failed to clone.  Don't worry about it, and just return
+                 * the original object. */
+            }
+        }
+
+        if ( clone == null ) {
+            clone = original;
+        }
+
+        return clone;
+    }
+
+    public static Object cloneArray(Object original) {
+        Object result = null;
+
+        if ( original.getClass().isArray() ) {
+            final int arrayLength = Array.getLength( original );
+
+            if ( arrayLength == 0 ) {
+                // empty arrays are immutable
+                result = original;
+            } else {
+                final Class componentType = original.getClass().getComponentType();
+
+                // Even though arrays implicitly have a public clone(), it
+                // cannot be invoked reflectively, so need to do copy construction:
+                result = Array.newInstance( componentType,
+                                            arrayLength );
+
+                if ( componentType.isArray() ) {
+                    for ( int i = 0; i < arrayLength; i++ ) {
+                        Array.set( result,
+                                   i,
+                                   cloneArray( Array.get( original,
+                                                          i ) ) );
+                    }
+                } else {
+                    System.arraycopy( original,
+                                      0,
+                                      result,
+                                      0,
+                                      arrayLength );
+                }
+            }
+        }
+        return result;
+    }
+    
+    /**
+     * Checks if a collection contains a given object taking
+     * appropriate care with the presence or not of shadow proxies
+     * 
+     * @param col
+     * @param obj
+     * @return
+     */
+    public static boolean contains( Collection col, Object obj ) {
+        if( col == null )
+            return false;
+        if( obj instanceof ShadowProxy ) {
+            // if obj is a shadow proxy, its equals() method
+            // implementation will take appropriate care when
+            // the collection is checked.
+            return col.contains( obj );
+        } else {
+            // otherwise, iterate over the collection 
+            // comparing each element. If the element
+            // is a shadow proxy, there is no problem, since
+            // its equals() method implementation handles 
+            // comparisons with non shadowed objects appropriately
+            for( Iterator it = col.iterator(); it.hasNext(); ) {
+                Object next = it.next();
+                if( next == null && obj == null ||
+                    next != null && next.equals( obj ) ) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Checks if an array contains a given object taking
+     * appropriate care with the presence or not of shadow proxies
+     * 
+     * @param col
+     * @param obj
+     * @return
+     */
+    public static boolean contains( Object[] array, Object obj ) {
+        if( array == null )
+            return false;
+        if( obj instanceof ShadowProxy ) {
+            // if obj is a shadow proxy, its equals() method
+            // implementation will take appropriate care when
+            // the array is checked.
+            for( int i = 0; i < array.length; i++ ) {
+                if( array[i] == null && obj == null ||
+                    obj != null && obj.equals( array[i] )) {
+                    return true;
+                }
+            }
+        } else {
+            // otherwise, iterate over the array 
+            // comparing each element. If the element
+            // is a shadow proxy, there is no problem, since
+            // its equals() method implementation handles 
+            // comparisons with non shadowed objects appropriately
+            for( int i = 0; i < array.length; i++ ) {
+                if( array[i] == null && obj == null ||
+                    array[i] != null && array[i].equals( obj )) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/StringUtils.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/StringUtils.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/StringUtils.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,776 @@
+package org.drools.util;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Ripped form commons StringUtil:
+ * 
+ * <p>Operations on {@link java.lang.String} that are
+ * <code>null</code> safe.</p>
+ *
+ * <ul>
+ *  <li><b>IsEmpty/IsBlank</b>
+ *      - checks if a String contains text</li>
+ *  <li><b>Trim/Strip</b>
+ *      - removes leading and trailing whitespace</li>
+ *  <li><b>Equals</b>
+ *      - compares two strings null-safe</li>
+ *  <li><b>IndexOf/LastIndexOf/Contains</b>
+ *      - null-safe index-of checks
+ *  <li><b>IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut</b>
+ *      - index-of any of a set of Strings</li>
+ *  <li><b>ContainsOnly/ContainsNone</b>
+ *      - does String contains only/none of these characters</li>
+ *  <li><b>Substring/Left/Right/Mid</b>
+ *      - null-safe substring extractions</li>
+ *  <li><b>SubstringBefore/SubstringAfter/SubstringBetween</b>
+ *      - substring extraction relative to other strings</li>
+ *  <li><b>Split/Join</b>
+ *      - splits a String into an array of substrings and vice versa</li>
+ *  <li><b>Remove/Delete</b>
+ *      - removes part of a String</li>
+ *  <li><b>Replace/Overlay</b>
+ *      - Searches a String and replaces one String with another</li>
+ *  <li><b>Chomp/Chop</b>
+ *      - removes the last part of a String</li>
+ *  <li><b>LeftPad/RightPad/Center/Repeat</b>
+ *      - pads a String</li>
+ *  <li><b>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</b>
+ *      - changes the case of a String</li>
+ *  <li><b>CountMatches</b>
+ *      - counts the number of occurrences of one String in another</li>
+ *  <li><b>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</b>
+ *      - checks the characters in a String</li>
+ *  <li><b>DefaultString</b>
+ *      - protects against a null input String</li>
+ *  <li><b>Reverse/ReverseDelimited</b>
+ *      - reverses a String</li>
+ *  <li><b>Abbreviate</b>
+ *      - abbreviates a string using ellipsis</li>
+ *  <li><b>Difference</b>
+ *      - compares two Strings and reports on their differences</li>
+ *  <li><b>LevensteinDistance</b>
+ *      - the number of changes needed to change one String into another</li>
+ * </ul>
+ *
+ * <p>The <code>StringUtils</code> class defines certain words related to
+ * String handling.</p>
+ *
+ * <ul>
+ *  <li>null - <code>null</code></li>
+ *  <li>empty - a zero-length string (<code>""</code>)</li>
+ *  <li>space - the space character (<code>' '</code>, char 32)</li>
+ *  <li>whitespace - the characters defined by {@link Character#isWhitespace(char)}</li>
+ *  <li>trim - the characters &lt;= 32 as in {@link String#trim()}</li>
+ * </ul>
+ *
+ * <p><code>StringUtils</code> handles <code>null</code> input Strings quietly.
+ * That is to say that a <code>null</code> input will return <code>null</code>.
+ * Where a <code>boolean</code> or <code>int</code> is being returned
+ * details vary by method.</p>
+ *
+ * <p>A side effect of the <code>null</code> handling is that a
+ * <code>NullPointerException</code> should be considered a bug in
+ * <code>StringUtils</code> (except for deprecated methods).</p>
+ *
+ * <p>Methods in this class give sample code to explain their operation.
+ * The symbol <code>*</code> is used to indicate any input including <code>null</code>.</p>
+ *
+ * @see java.lang.String
+ * @author <a href="http://jakarta.apache.org/turbine/">Apache Jakarta Turbine</a>
+ * @author <a href="mailto:jon at latchkey.com">Jon S. Stevens</a>
+ * @author <a href="mailto:dlr at finemaltcoding.com">Daniel Rall</a>
+ * @author <a href="mailto:gcoladonato at yahoo.com">Greg Coladonato</a>
+ * @author <a href="mailto:ed at apache.org">Ed Korthof</a>
+ * @author <a href="mailto:rand_mcneely at yahoo.com">Rand McNeely</a>
+ * @author Stephen Colebourne
+ * @author <a href="mailto:fredrik at westermarck.com">Fredrik Westermarck</a>
+ * @author Holger Krauth
+ * @author <a href="mailto:alex at purpletech.com">Alexander Day Chaffee</a>
+ * @author <a href="mailto:hps at intermeta.de">Henning P. Schmiedehausen</a>
+ * @author Arun Mammen Thomas
+ * @author Gary Gregory
+ * @author Phil Steitz
+ * @author Al Chou
+ * @author Michael Davey
+ * @author Reuben Sivan
+ * @author Chris Hyzer
+ * @since 1.0
+ * @version $Id$
+ */
+public class StringUtils {
+
+    /**
+     * An empty immutable <code>String</code> array.
+     */
+    public static final String[] EMPTY_STRING_ARRAY = new String[0];
+
+    // Performance testing notes (JDK 1.4, Jul03, scolebourne)
+    // Whitespace:
+    // Character.isWhitespace() is faster than WHITESPACE.indexOf()
+    // where WHITESPACE is a string of all whitespace characters
+    //
+    // Character access:
+    // String.charAt(n) versus toCharArray(), then array[n]
+    // String.charAt(n) is about 15% worse for a 10K string
+    // They are about equal for a length 50 string
+    // String.charAt(n) is about 4 times better for a length 3 string
+    // String.charAt(n) is best bet overall
+    //
+    // Append:
+    // String.concat about twice as fast as StringBuffer.append
+    // (not sure who tested this)
+
+    /**
+     * The empty String <code>""</code>.
+     * @since 2.0
+     */
+    public static final String   EMPTY              = "";
+
+    /**
+     * Represents a failed index search.
+     * @since 2.1
+     */
+    public static final int      INDEX_NOT_FOUND    = -1;
+
+    /**
+     * <p>The maximum size to which the padding constant(s) can expand.</p>
+     */
+    private static final int     PAD_LIMIT          = 8192;
+
+    /**
+     * <p><code>StringUtils</code> instances should NOT be constructed in
+     * standard programming. Instead, the class should be used as
+     * <code>StringUtils.trim(" foo ");</code>.</p>
+     *
+     * <p>This constructor is public to permit tools that require a JavaBean
+     * instance to operate.</p>
+     */
+    public StringUtils() {
+        super();
+    }
+
+    public static String ucFirst(final String name) {
+        return name.toUpperCase().charAt( 0 ) + name.substring( 1 );
+    }
+
+    // Empty checks
+    //-----------------------------------------------------------------------
+    /**
+     * <p>Checks if a String is empty ("") or null.</p>
+     *
+     * <pre>
+     * StringUtils.isEmpty(null)      = true
+     * StringUtils.isEmpty("")        = true
+     * StringUtils.isEmpty(" ")       = false
+     * StringUtils.isEmpty("bob")     = false
+     * StringUtils.isEmpty("  bob  ") = false
+     * </pre>
+     *
+     * <p>NOTE: This method changed in Lang version 2.0.
+     * It no longer trims the String.
+     * That functionality is available in isBlank().</p>
+     *
+     * @param str  the String to check, may be null
+     * @return <code>true</code> if the String is empty or null
+     */
+    public static boolean isEmpty(final String str) {
+        return str == null || str.length() == 0;
+    }
+
+    // Padding
+    //-----------------------------------------------------------------------
+    /**
+     * <p>Repeat a String <code>repeat</code> times to form a
+     * new String.</p>
+     *
+     * <pre>
+     * StringUtils.repeat(null, 2) = null
+     * StringUtils.repeat("", 0)   = ""
+     * StringUtils.repeat("", 2)   = ""
+     * StringUtils.repeat("a", 3)  = "aaa"
+     * StringUtils.repeat("ab", 2) = "abab"
+     * StringUtils.repeat("a", -2) = ""
+     * </pre>
+     *
+     * @param str  the String to repeat, may be null
+     * @param repeat  number of times to repeat str, negative treated as zero
+     * @return a new String consisting of the original String repeated,
+     *  <code>null</code> if null String input
+     */
+    public static String repeat(final String str,
+                                final int repeat) {
+        // Performance tuned for 2.0 (JDK1.4)
+
+        if ( str == null ) {
+            return null;
+        }
+        if ( repeat <= 0 ) {
+            return EMPTY;
+        }
+        final int inputLength = str.length();
+        if ( repeat == 1 || inputLength == 0 ) {
+            return str;
+        }
+        if ( inputLength == 1 && repeat <= PAD_LIMIT ) {
+            return padding( repeat,
+                            str.charAt( 0 ) );
+        }
+
+        final int outputLength = inputLength * repeat;
+        switch ( inputLength ) {
+            case 1 :
+                final char ch = str.charAt( 0 );
+                final char[] output1 = new char[outputLength];
+                for ( int i = repeat - 1; i >= 0; i-- ) {
+                    output1[i] = ch;
+                }
+                return new String( output1 );
+            case 2 :
+                final char ch0 = str.charAt( 0 );
+                final char ch1 = str.charAt( 1 );
+                final char[] output2 = new char[outputLength];
+                for ( int i = repeat * 2 - 2; i >= 0; i--, i-- ) {
+                    output2[i] = ch0;
+                    output2[i + 1] = ch1;
+                }
+                return new String( output2 );
+            default :
+                final StringBuffer buf = new StringBuffer( outputLength );
+                for ( int i = 0; i < repeat; i++ ) {
+                    buf.append( str );
+                }
+                return buf.toString();
+        }
+    }
+
+    // Splitting
+    //-----------------------------------------------------------------------
+    /**
+     * <p>Splits the provided text into an array, using whitespace as the
+     * separator.
+     * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
+     *
+     * <p>The separator is not included in the returned String array.
+     * Adjacent separators are treated as one separator.
+     * For more control over the split use the StrTokenizer class.</p>
+     *
+     * <p>A <code>null</code> input String returns <code>null</code>.</p>
+     *
+     * <pre>
+     * StringUtils.split(null)       = null
+     * StringUtils.split("")         = []
+     * StringUtils.split("abc def")  = ["abc", "def"]
+     * StringUtils.split("abc  def") = ["abc", "def"]
+     * StringUtils.split(" abc ")    = ["abc"]
+     * </pre>
+     *
+     * @param str  the String to parse, may be null
+     * @return an array of parsed Strings, <code>null</code> if null String input
+     */
+    public static String[] split(String str) {
+        return split( str,
+                      null,
+                      -1 );
+    }
+
+    /**
+     * <p>Splits the provided text into an array, separator specified.
+     * This is an alternative to using StringTokenizer.</p>
+     *
+     * <p>The separator is not included in the returned String array.
+     * Adjacent separators are treated as one separator.
+     * For more control over the split use the StrTokenizer class.</p>
+     *
+     * <p>A <code>null</code> input String returns <code>null</code>.</p>
+     *
+     * <pre>
+     * StringUtils.split(null, *)         = null
+     * StringUtils.split("", *)           = []
+     * StringUtils.split("a.b.c", '.')    = ["a", "b", "c"]
+     * StringUtils.split("a..b.c", '.')   = ["a", "b", "c"]
+     * StringUtils.split("a:b:c", '.')    = ["a:b:c"]
+     * StringUtils.split("a\tb\nc", null) = ["a", "b", "c"]
+     * StringUtils.split("a b c", ' ')    = ["a", "b", "c"]
+     * </pre>
+     *
+     * @param str  the String to parse, may be null
+     * @param separatorChar  the character used as the delimiter,
+     *  <code>null</code> splits on whitespace
+     * @return an array of parsed Strings, <code>null</code> if null String input
+     * @since 2.0
+     */
+    public static String[] split(String str,
+                                 char separatorChar) {
+        return splitWorker( str,
+                            separatorChar,
+                            false );
+    }
+
+    /**
+     * <p>Splits the provided text into an array, separators specified.
+     * This is an alternative to using StringTokenizer.</p>
+     *
+     * <p>The separator is not included in the returned String array.
+     * Adjacent separators are treated as one separator.
+     * For more control over the split use the StrTokenizer class.</p>
+     *
+     * <p>A <code>null</code> input String returns <code>null</code>.
+     * A <code>null</code> separatorChars splits on whitespace.</p>
+     *
+     * <pre>
+     * StringUtils.split(null, *)         = null
+     * StringUtils.split("", *)           = []
+     * StringUtils.split("abc def", null) = ["abc", "def"]
+     * StringUtils.split("abc def", " ")  = ["abc", "def"]
+     * StringUtils.split("abc  def", " ") = ["abc", "def"]
+     * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
+     * </pre>
+     *
+     * @param str  the String to parse, may be null
+     * @param separatorChars  the characters used as the delimiters,
+     *  <code>null</code> splits on whitespace
+     * @return an array of parsed Strings, <code>null</code> if null String input
+     */
+    public static String[] split(String str,
+                                 String separatorChars) {
+        return splitWorker( str,
+                            separatorChars,
+                            -1,
+                            false );
+    }
+
+    /**
+     * <p>Splits the provided text into an array with a maximum length,
+     * separators specified.</p>
+     *
+     * <p>The separator is not included in the returned String array.
+     * Adjacent separators are treated as one separator.</p>
+     *
+     * <p>A <code>null</code> input String returns <code>null</code>.
+     * A <code>null</code> separatorChars splits on whitespace.</p>
+     *
+     * <p>If more than <code>min</code> delimited substrings are found, the last
+     * returned string includes all characters after the first <code>min - 1</code>
+     * returned strings (including separator characters).</p>
+     *
+     * <pre>
+     * StringUtils.split(null, *, *)            = null
+     * StringUtils.split("", *, *)              = []
+     * StringUtils.split("ab de fg", null, 0)   = ["ab", "cd", "ef"]
+     * StringUtils.split("ab   de fg", null, 0) = ["ab", "cd", "ef"]
+     * StringUtils.split("ab:cd:ef", ":", 0)    = ["ab", "cd", "ef"]
+     * StringUtils.split("ab:cd:ef", ":", 2)    = ["ab", "cd:ef"]
+     * </pre>
+     *
+     * @param str  the String to parse, may be null
+     * @param separatorChars  the characters used as the delimiters,
+     *  <code>null</code> splits on whitespace
+     * @param min  the maximum number of elements to include in the
+     *  array. A zero or negative value implies no limit
+     * @return an array of parsed Strings, <code>null</code> if null String input
+     */
+    public static String[] split(String str,
+                                 String separatorChars,
+                                 int max) {
+        return splitWorker( str,
+                            separatorChars,
+                            max,
+                            false );
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * <p>Splits the provided text into an array, using whitespace as the
+     * separator, preserving all tokens, including empty tokens created by 
+     * adjacent separators. This is an alternative to using StringTokenizer.
+     * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
+     *
+     * <p>The separator is not included in the returned String array.
+     * Adjacent separators are treated as separators for empty tokens.
+     * For more control over the split use the StrTokenizer class.</p>
+     *
+     * <p>A <code>null</code> input String returns <code>null</code>.</p>
+     *
+     * <pre>
+     * StringUtils.splitPreserveAllTokens(null)       = null
+     * StringUtils.splitPreserveAllTokens("")         = []
+     * StringUtils.splitPreserveAllTokens("abc def")  = ["abc", "def"]
+     * StringUtils.splitPreserveAllTokens("abc  def") = ["abc", "", "def"]
+     * StringUtils.splitPreserveAllTokens(" abc ")    = ["", "abc", ""]
+     * </pre>
+     *
+     * @param str  the String to parse, may be <code>null</code>
+     * @return an array of parsed Strings, <code>null</code> if null String input
+     * @since 2.1
+     */
+    public static String[] splitPreserveAllTokens(final String str) {
+        return splitWorker( str,
+                            null,
+                            -1,
+                            true );
+    }
+
+    /**
+     * <p>Splits the provided text into an array, separator specified,
+     * preserving all tokens, including empty tokens created by adjacent
+     * separators. This is an alternative to using StringTokenizer.</p>
+     *
+     * <p>The separator is not included in the returned String array.
+     * Adjacent separators are treated as separators for empty tokens.
+     * For more control over the split use the StrTokenizer class.</p>
+     *
+     * <p>A <code>null</code> input String returns <code>null</code>.</p>
+     *
+     * <pre>
+     * StringUtils.splitPreserveAllTokens(null, *)         = null
+     * StringUtils.splitPreserveAllTokens("", *)           = []
+     * StringUtils.splitPreserveAllTokens("a.b.c", '.')    = ["a", "b", "c"]
+     * StringUtils.splitPreserveAllTokens("a..b.c", '.')   = ["a", "", "b", "c"]
+     * StringUtils.splitPreserveAllTokens("a:b:c", '.')    = ["a:b:c"]
+     * StringUtils.splitPreserveAllTokens("a\tb\nc", null) = ["a", "b", "c"]
+     * StringUtils.splitPreserveAllTokens("a b c", ' ')    = ["a", "b", "c"]
+     * StringUtils.splitPreserveAllTokens("a b c ", ' ')   = ["a", "b", "c", ""]
+     * StringUtils.splitPreserveAllTokens("a b c  ", ' ')   = ["a", "b", "c", "", ""]
+     * StringUtils.splitPreserveAllTokens(" a b c", ' ')   = ["", a", "b", "c"]
+     * StringUtils.splitPreserveAllTokens("  a b c", ' ')  = ["", "", a", "b", "c"]
+     * StringUtils.splitPreserveAllTokens(" a b c ", ' ')  = ["", a", "b", "c", ""]
+     * </pre>
+     *
+     * @param str  the String to parse, may be <code>null</code>
+     * @param separatorChar  the character used as the delimiter,
+     *  <code>null</code> splits on whitespace
+     * @return an array of parsed Strings, <code>null</code> if null String input
+     * @since 2.1
+     */
+    public static String[] splitPreserveAllTokens(final String str,
+                                                  final char separatorChar) {
+        return splitWorker( str,
+                            separatorChar,
+                            true );
+    }
+
+    /**
+     * Performs the logic for the <code>split</code> and 
+     * <code>splitPreserveAllTokens</code> methods that do not return a
+     * maximum array length.
+     *
+     * @param str  the String to parse, may be <code>null</code>
+     * @param separatorChar the separate character
+     * @param preserveAllTokens if <code>true</code>, adjacent separators are
+     * treated as empty token separators; if <code>false</code>, adjacent
+     * separators are treated as one separator.
+     * @return an array of parsed Strings, <code>null</code> if null String input
+     */
+    private static String[] splitWorker(final String str,
+                                        final char separatorChar,
+                                        final boolean preserveAllTokens) {
+        // Performance tuned for 2.0 (JDK1.4)
+
+        if ( str == null ) {
+            return null;
+        }
+        final int len = str.length();
+        if ( len == 0 ) {
+            return EMPTY_STRING_ARRAY;
+        }
+        final List list = new ArrayList();
+        int i = 0, start = 0;
+        boolean match = false;
+        boolean lastMatch = false;
+        while ( i < len ) {
+            if ( str.charAt( i ) == separatorChar ) {
+                if ( match || preserveAllTokens ) {
+                    list.add( str.substring( start,
+                                             i ) );
+                    match = false;
+                    lastMatch = true;
+                }
+                start = ++i;
+                continue;
+            } else {
+                lastMatch = false;
+            }
+            match = true;
+            i++;
+        }
+        if ( match || (preserveAllTokens && lastMatch) ) {
+            list.add( str.substring( start,
+                                     i ) );
+        }
+        return (String[]) list.toArray( new String[list.size()] );
+    }
+
+    /**
+     * <p>Splits the provided text into an array, separators specified, 
+     * preserving all tokens, including empty tokens created by adjacent
+     * separators. This is an alternative to using StringTokenizer.</p>
+     *
+     * <p>The separator is not included in the returned String array.
+     * Adjacent separators are treated as separators for empty tokens.
+     * For more control over the split use the StrTokenizer class.</p>
+     *
+     * <p>A <code>null</code> input String returns <code>null</code>.
+     * A <code>null</code> separatorChars splits on whitespace.</p>
+     *
+     * <pre>
+     * StringUtils.splitPreserveAllTokens(null, *)           = null
+     * StringUtils.splitPreserveAllTokens("", *)             = []
+     * StringUtils.splitPreserveAllTokens("abc def", null)   = ["abc", "def"]
+     * StringUtils.splitPreserveAllTokens("abc def", " ")    = ["abc", "def"]
+     * StringUtils.splitPreserveAllTokens("abc  def", " ")   = ["abc", "", def"]
+     * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":")   = ["ab", "cd", "ef"]
+     * StringUtils.splitPreserveAllTokens("ab:cd:ef:", ":")  = ["ab", "cd", "ef", ""]
+     * StringUtils.splitPreserveAllTokens("ab:cd:ef::", ":") = ["ab", "cd", "ef", "", ""]
+     * StringUtils.splitPreserveAllTokens("ab::cd:ef", ":")  = ["ab", "", cd", "ef"]
+     * StringUtils.splitPreserveAllTokens(":cd:ef", ":")     = ["", cd", "ef"]
+     * StringUtils.splitPreserveAllTokens("::cd:ef", ":")    = ["", "", cd", "ef"]
+     * StringUtils.splitPreserveAllTokens(":cd:ef:", ":")    = ["", cd", "ef", ""]
+     * </pre>
+     *
+     * @param str  the String to parse, may be <code>null</code>
+     * @param separatorChars  the characters used as the delimiters,
+     *  <code>null</code> splits on whitespace
+     * @return an array of parsed Strings, <code>null</code> if null String input
+     * @since 2.1
+     */
+    public static String[] splitPreserveAllTokens(final String str,
+                                                  final String separatorChars) {
+        return splitWorker( str,
+                            separatorChars,
+                            -1,
+                            true );
+    }
+
+    /**
+     * <p>Splits the provided text into an array with a maximum length,
+     * separators specified, preserving all tokens, including empty tokens 
+     * created by adjacent separators.</p>
+     *
+     * <p>The separator is not included in the returned String array.
+     * Adjacent separators are treated as separators for empty tokens.
+     * Adjacent separators are treated as one separator.</p>
+     *
+     * <p>A <code>null</code> input String returns <code>null</code>.
+     * A <code>null</code> separatorChars splits on whitespace.</p>
+     *
+     * <p>If more than <code>min</code> delimited substrings are found, the last
+     * returned string includes all characters after the first <code>min - 1</code>
+     * returned strings (including separator characters).</p>
+     *
+     * <pre>
+     * StringUtils.splitPreserveAllTokens(null, *, *)            = null
+     * StringUtils.splitPreserveAllTokens("", *, *)              = []
+     * StringUtils.splitPreserveAllTokens("ab de fg", null, 0)   = ["ab", "cd", "ef"]
+     * StringUtils.splitPreserveAllTokens("ab   de fg", null, 0) = ["ab", "cd", "ef"]
+     * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 0)    = ["ab", "cd", "ef"]
+     * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2)    = ["ab", "cd:ef"]
+     * StringUtils.splitPreserveAllTokens("ab   de fg", null, 2) = ["ab", "  de fg"]
+     * StringUtils.splitPreserveAllTokens("ab   de fg", null, 3) = ["ab", "", " de fg"]
+     * StringUtils.splitPreserveAllTokens("ab   de fg", null, 4) = ["ab", "", "", "de fg"]
+     * </pre>
+     *
+     * @param str  the String to parse, may be <code>null</code>
+     * @param separatorChars  the characters used as the delimiters,
+     *  <code>null</code> splits on whitespace
+     * @param min  the maximum number of elements to include in the
+     *  array. A zero or negative value implies no limit
+     * @return an array of parsed Strings, <code>null</code> if null String input
+     * @since 2.1
+     */
+    public static String[] splitPreserveAllTokens(final String str,
+                                                  final String separatorChars,
+                                                  final int max) {
+        return splitWorker( str,
+                            separatorChars,
+                            max,
+                            true );
+    }
+
+    /**
+     * Performs the logic for the <code>split</code> and 
+     * <code>splitPreserveAllTokens</code> methods that return a maximum array 
+     * length.
+     *
+     * @param str  the String to parse, may be <code>null</code>
+     * @param separatorChars the separate character
+     * @param min  the maximum number of elements to include in the
+     *  array. A zero or negative value implies no limit.
+     * @param preserveAllTokens if <code>true</code>, adjacent separators are
+     * treated as empty token separators; if <code>false</code>, adjacent
+     * separators are treated as one separator.
+     * @return an array of parsed Strings, <code>null</code> if null String input
+     */
+    private static String[] splitWorker(final String str,
+                                        final String separatorChars,
+                                        final int max,
+                                        final boolean preserveAllTokens) {
+        // Performance tuned for 2.0 (JDK1.4)
+        // Direct code is quicker than StringTokenizer.
+        // Also, StringTokenizer uses isSpace() not isWhitespace()
+
+        if ( str == null ) {
+            return null;
+        }
+        final int len = str.length();
+        if ( len == 0 ) {
+            return EMPTY_STRING_ARRAY;
+        }
+        final List list = new ArrayList();
+        int sizePlus1 = 1;
+        int i = 0, start = 0;
+        boolean match = false;
+        boolean lastMatch = false;
+        if ( separatorChars == null ) {
+            // Null separator means use whitespace
+            while ( i < len ) {
+                if ( Character.isWhitespace( str.charAt( i ) ) ) {
+                    if ( match || preserveAllTokens ) {
+                        lastMatch = true;
+                        if ( sizePlus1++ == max ) {
+                            i = len;
+                            lastMatch = false;
+                        }
+                        list.add( str.substring( start,
+                                                 i ) );
+                        match = false;
+                    }
+                    start = ++i;
+                    continue;
+                } else {
+                    lastMatch = false;
+                }
+                match = true;
+                i++;
+            }
+        } else if ( separatorChars.length() == 1 ) {
+            // Optimise 1 character case
+            final char sep = separatorChars.charAt( 0 );
+            while ( i < len ) {
+                if ( str.charAt( i ) == sep ) {
+                    if ( match || preserveAllTokens ) {
+                        lastMatch = true;
+                        if ( sizePlus1++ == max ) {
+                            i = len;
+                            lastMatch = false;
+                        }
+                        list.add( str.substring( start,
+                                                 i ) );
+                        match = false;
+                    }
+                    start = ++i;
+                    continue;
+                } else {
+                    lastMatch = false;
+                }
+                match = true;
+                i++;
+            }
+        } else {
+            // standard case
+            while ( i < len ) {
+                if ( separatorChars.indexOf( str.charAt( i ) ) >= 0 ) {
+                    if ( match || preserveAllTokens ) {
+                        lastMatch = true;
+                        if ( sizePlus1++ == max ) {
+                            i = len;
+                            lastMatch = false;
+                        }
+                        list.add( str.substring( start,
+                                                 i ) );
+                        match = false;
+                    }
+                    start = ++i;
+                    continue;
+                } else {
+                    lastMatch = false;
+                }
+                match = true;
+                i++;
+            }
+        }
+        if ( match || (preserveAllTokens && lastMatch) ) {
+            list.add( str.substring( start,
+                                     i ) );
+        }
+        return (String[]) list.toArray( new String[list.size()] );
+    }
+
+    /**
+     * <p>Returns padding using the specified delimiter repeated
+     * to a given length.</p>
+     *
+     * <pre>
+     * StringUtils.padding(0, 'e')  = ""
+     * StringUtils.padding(3, 'e')  = "eee"
+     * StringUtils.padding(-2, 'e') = IndexOutOfBoundsException
+     * </pre>
+     *
+     * <p>Note: this method doesn't not support padding with
+     * <a href="http://www.unicode.org/glossary/#supplementary_character">Unicode Supplementary Characters</a>
+     * as they require a pair of <code>char</code>s to be represented.
+     * If you are needing to support full I18N of your applications
+     * consider using {@link #repeat(String, int)} instead. 
+     * </p>
+     *
+     * @param repeat  number of times to repeat delim
+     * @param padChar  character to repeat
+     * @return String with repeated character
+     * @throws IndexOutOfBoundsException if <code>repeat &lt; 0</code>
+     * @see #repeat(String, int)
+     */
+    public static String padding(final int repeat,
+                                 final char padChar) throws IndexOutOfBoundsException {
+        if ( repeat < 0 ) {
+            throw new IndexOutOfBoundsException( "Cannot pad a negative amount: " + repeat );
+        }
+        final char[] buf = new char[repeat];
+        for ( int i = 0; i < buf.length; i++ ) {
+            buf[i] = padChar;
+        }
+        return new String( buf );
+    }
+
+    /** @param filePath the name of the file to open. Not sure if it can accept URLs or just filenames. Path handling could be better, and buffer sizes are hardcoded
+     */
+    public static String readFileAsString(Reader reader) {
+        try {
+            StringBuffer fileData = new StringBuffer( 1000 );
+            char[] buf = new char[1024];
+            int numRead = 0;
+            while ( (numRead = reader.read( buf )) != -1 ) {
+                String readData = String.valueOf( buf,
+                                                  0,
+                                                  numRead );
+                fileData.append( readData );
+                buf = new char[1024];
+            }
+            reader.close();
+            return fileData.toString();
+        } catch ( IOException e ) {
+            throw new RuntimeException( e );
+        }
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ThreadSafeJavaIteratorAdapter.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ThreadSafeJavaIteratorAdapter.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/ThreadSafeJavaIteratorAdapter.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,5 @@
+package org.drools.util;
+
+public class ThreadSafeJavaIteratorAdapter {
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/TupleHashTable.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/TupleHashTable.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/TupleHashTable.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,101 @@
+/**
+ * 
+ */
+package org.drools.util;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.reteoo.ReteTuple;
+import org.drools.reteoo.TupleMemory;
+
+public class TupleHashTable extends AbstractHashTable
+    implements
+    TupleMemory {
+    public TupleHashTable() {
+        this( 16,
+              0.75f );
+    }
+
+    public TupleHashTable(final int capacity,
+                          final float loadFactor) {
+        super( capacity,
+               loadFactor );
+    }
+
+    public Iterator iterator(final InternalFactHandle handle) {
+        return iterator();
+    }
+
+    public void add(final ReteTuple tuple) {
+        final int hashCode = tuple.hashCode();
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+
+        tuple.setNext( this.table[index] );
+        this.table[index] = tuple;
+
+        if ( this.size++ >= this.threshold ) {
+            resize( 2 * this.table.length );
+        }
+    }
+
+    public ReteTuple get(final ReteTuple tuple) {
+        final int hashCode = tuple.hashCode();
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+
+        ReteTuple current = (ReteTuple) this.table[index];
+        while ( current != null ) {
+            if ( hashCode == current.hashCode() && tuple.equals( current ) ) {
+                return current;
+            }
+            current = (ReteTuple) current.getNext();
+        }
+        return null;
+    }
+
+    public ReteTuple remove(final ReteTuple tuple) {
+        final int hashCode = tuple.hashCode();
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+
+        ReteTuple previous = (ReteTuple) this.table[index];
+        ReteTuple current = previous;
+        while ( current != null ) {
+            final ReteTuple next = (ReteTuple) current.getNext();
+            if ( hashCode == current.hashCode() && tuple.equals( current ) ) {
+                if ( previous == current ) {
+                    this.table[index] = next;
+                } else {
+                    previous.setNext( next );
+                }
+                current.setNext( null );
+                this.size--;
+                return current;
+            }
+            previous = current;
+            current = next;
+        }
+        return current;
+    }
+
+    public Entry getBucket(final Object object) {
+        final int hashCode = object.hashCode();
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+
+        return this.table[index];
+    }
+
+    public boolean contains(final ReteTuple tuple) {
+        return (get( tuple ) != null);
+    }
+
+    public boolean isIndexed() {
+        return false;
+    }
+
+	@Override
+	public ReteTuple peek() {
+		throw new UnsupportedOperationException( "TupleHashTable does not support  peek()" );
+	}
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/TupleIndexHashTable.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/TupleIndexHashTable.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/TupleIndexHashTable.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,404 @@
+/**
+ * 
+ */
+package org.drools.util;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.reteoo.ReteTuple;
+import org.drools.reteoo.TupleMemory;
+
+public class TupleIndexHashTable extends AbstractHashTable
+    implements
+    TupleMemory {
+
+    private static final long               serialVersionUID = 400L;
+
+    public static final int                 PRIME            = 31;
+
+    private int                             startResult;
+
+    private FieldIndexHashTableIterator     tupleValueIterator;
+    private FieldIndexHashTableFullIterator tupleValueFullIterator;
+
+    private int                             factSize;
+
+    private Index                           index;
+
+    public TupleIndexHashTable(final FieldIndex[] index) {
+        this( 16,
+              0.75f,
+              index );
+    }
+
+    public TupleIndexHashTable(final int capacity,
+                               final float loadFactor,
+                               final FieldIndex[] index) {
+        super( capacity,
+               loadFactor );
+
+        this.startResult = TupleIndexHashTable.PRIME;
+        for ( int i = 0, length = index.length; i < length; i++ ) {
+            this.startResult += TupleIndexHashTable.PRIME * this.startResult + index[i].getExtractor().getIndex();
+        }
+
+        switch ( index.length ) {
+            case 0 :
+                throw new IllegalArgumentException( "FieldIndexHashTable cannot use an index[] of length  0" );
+            case 1 :
+                this.index = new SingleIndex( index,
+                                              this.startResult );
+                break;
+            case 2 :
+                this.index = new DoubleCompositeIndex( index,
+                                                       this.startResult );
+                break;
+            case 3 :
+                this.index = new TripleCompositeIndex( index,
+                                                       this.startResult );
+                break;
+            default :
+                throw new IllegalArgumentException( "FieldIndexHashTable cannot use an index[] of length  great than 3" );
+        }
+    }
+
+    public Iterator iterator() {
+        if ( this.tupleValueFullIterator == null ) {
+            this.tupleValueFullIterator = new FieldIndexHashTableFullIterator( this );
+        }
+        this.tupleValueFullIterator.reset();
+        return this.tupleValueFullIterator;
+    }
+
+    public Iterator iterator(final InternalFactHandle handle) {
+        if ( this.tupleValueIterator == null ) {
+            this.tupleValueIterator = new FieldIndexHashTableIterator();
+        }
+        final FieldIndexEntry entry = get( handle );
+        this.tupleValueIterator.reset( (entry != null) ? entry.first : null );
+        return this.tupleValueIterator;
+    }
+
+    public boolean isIndexed() {
+        return true;
+    }
+    
+    public Index getIndex() {
+        return this.index;
+    }
+
+    public Entry getBucket(final Object object) {
+        final int hashCode = this.index.hashCodeOf( object );
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+
+        return this.table[index];
+    }
+
+    /**
+     * Fast re-usable iterator
+     *
+     */
+    public static class FieldIndexHashTableIterator
+        implements
+        Iterator {
+        private Entry entry;
+
+        public FieldIndexHashTableIterator() {
+
+        }
+
+        /* (non-Javadoc)
+         * @see org.drools.util.Iterator#next()
+         */
+        public Object next() {
+            final Entry current = this.entry;
+            this.entry = (this.entry != null) ? this.entry.getNext() : null;
+            return current;
+        }
+
+        /* (non-Javadoc)
+         * @see org.drools.util.Iterator#reset()
+         */
+        public void reset(final Entry entry) {
+            this.entry = entry;
+        }
+    }
+
+    public static class FieldIndexHashTableFullIterator
+        implements
+        Iterator {
+        private AbstractHashTable hashTable;
+        private Entry[]           table;
+        private int               row;
+        private int               length;
+        private Entry             entry;
+
+        public FieldIndexHashTableFullIterator(final AbstractHashTable hashTable) {
+            this.hashTable = hashTable;
+        }
+
+        /* (non-Javadoc)
+         * @see org.drools.util.Iterator#next()
+         */
+        public Object next() {
+            if ( this.entry == null ) {
+                // keep skipping rows until we come to the end, or find one that is populated
+                while ( this.entry == null ) {
+                    this.row++;
+                    if ( this.row == this.length ) {
+                        return null;
+                    }
+                    this.entry = (this.table[this.row] != null) ? ((FieldIndexEntry) this.table[this.row]).first : null;
+                }
+            } else {
+                this.entry = this.entry.getNext();
+                if ( this.entry == null ) {
+                    this.entry = (Entry) next();
+                }
+            }
+
+            return this.entry;
+        }
+
+        /* (non-Javadoc)
+         * @see org.drools.util.Iterator#reset()
+         */
+        public void reset() {
+            this.table = this.hashTable.getTable();
+            this.length = this.table.length;
+            this.row = -1;
+            this.entry = null;
+        }
+    }
+    
+    public Entry[] toArray() {
+        Entry[] result = new Entry[this.factSize];
+        int index = 0;
+        for ( int i = 0; i < this.table.length; i++ ) {
+            FieldIndexEntry fieldIndexEntry = (FieldIndexEntry)this.table[i];
+            while ( fieldIndexEntry != null ) {
+                Entry entry = fieldIndexEntry.getFirst();
+                while ( entry != null ) {
+                    result[index++] = entry;
+                    entry = entry.getNext();
+                }       
+                fieldIndexEntry  = ( FieldIndexEntry ) fieldIndexEntry.getNext();
+            }
+        }
+        return result;
+    }       
+
+    public void add(final ReteTuple tuple) {
+        final FieldIndexEntry entry = getOrCreate( tuple );
+        entry.add( tuple );
+        this.factSize++;
+    }
+
+    public boolean add(final ReteTuple tuple,
+                       final boolean checkExists) {
+        throw new UnsupportedOperationException( "FieldIndexHashTable does not support add(ReteTuple tuple, boolean checkExists)" );
+    }
+
+    public ReteTuple remove(final ReteTuple tuple) {
+        final int hashCode = this.index.hashCodeOf( tuple );
+
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+
+        // search the table for  the Entry, we need to track previous  and next, so if the 
+        // Entry is empty after  its had the FactEntry removed, we must remove  it from the table
+        FieldIndexEntry previous = (FieldIndexEntry) this.table[index];
+        FieldIndexEntry current = previous;
+        while ( current != null ) {
+            final FieldIndexEntry next = (FieldIndexEntry) current.next;
+            if ( current.matches( tuple,
+                                  hashCode ) ) {
+                final ReteTuple old = current.remove( tuple );
+                this.factSize--;
+                // If the FactEntryIndex is empty, then remove it from the hash table
+                if ( current.first == null ) {
+                    if ( previous == current ) {
+                        this.table[index] = next;
+                    } else {
+                        previous.next = next;
+                    }
+                    current.next = null;
+                    this.size--;
+                }
+                return old;
+            }
+            previous = current;
+            current = next;
+        }
+        return null;
+    }
+
+    public boolean contains(final ReteTuple tuple) {
+        final int hashCode = this.index.hashCodeOf( tuple );
+
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+
+        FieldIndexEntry current = (FieldIndexEntry) this.table[index];
+        while ( current != null ) {
+            if ( current.matches( tuple,
+                                  hashCode ) ) {
+                return true;
+            }
+            current = (FieldIndexEntry) current.next;
+        }
+        return false;
+    }
+
+    public FieldIndexEntry get(final InternalFactHandle handle) {
+        final Object object = handle.getObject();
+        final int hashCode = this.index.hashCodeOf( handle.getObject() );
+
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+        FieldIndexEntry entry = (FieldIndexEntry) this.table[index];
+
+        while ( entry != null ) {
+            if ( entry.matches( object,
+                                hashCode ) ) {
+                return entry;
+            }
+            entry = (FieldIndexEntry) entry.getNext();
+        }
+
+        return entry;
+    }
+
+    /**
+     * We use this method to aviod to table lookups for the same hashcode; which is what we would have to do if we did
+     * a get and then a create if the value is null.
+     * 
+     * @param value
+     * @return
+     */
+    private FieldIndexEntry getOrCreate(final ReteTuple tuple) {
+        final int hashCode = this.index.hashCodeOf( tuple );
+
+        final int index = indexOf( hashCode,
+                                   this.table.length );
+        FieldIndexEntry entry = (FieldIndexEntry) this.table[index];
+
+        // search to find an existing entry
+        while ( entry != null ) {
+            if ( entry.matches( tuple,
+                                hashCode ) ) {
+                return entry;
+            }
+            entry = (FieldIndexEntry) entry.next;
+        }
+
+        // entry does not exist, so create
+        if ( entry == null ) {
+            entry = new FieldIndexEntry( this.index,
+                                         hashCode );
+            entry.next = this.table[index];
+            this.table[index] = entry;
+
+            if ( this.size++ >= this.threshold ) {
+                resize( 2 * this.table.length );
+            }
+        }
+        return entry;
+    }
+
+    public int size() {
+        return this.factSize;
+    }
+
+    public static class FieldIndexEntry
+        implements
+        Entry {
+
+        private static final long serialVersionUID = 400L;
+        private Entry             next;
+        private ReteTuple         first;
+        private final int         hashCode;
+        private Index             index;
+
+        public FieldIndexEntry(final Index index,
+                               final int hashCode) {
+            this.index = index;
+            this.hashCode = hashCode;
+        }
+
+        public Entry getNext() {
+            return this.next;
+        }
+
+        public void setNext(final Entry next) {
+            this.next = next;
+        }
+
+        public ReteTuple getFirst() {
+            return this.first;
+        }
+
+        public void add(final ReteTuple tuple) {
+            tuple.setNext( this.first );
+            this.first = tuple;
+        }
+
+        public ReteTuple get(final ReteTuple tuple) {
+            ReteTuple current = this.first;
+            while ( current != null ) {
+                if ( tuple.equals( current ) ) {
+                    return current;
+                }
+                current = (ReteTuple) current.getNext();
+            }
+            return null;
+        }
+
+        public ReteTuple remove(final ReteTuple tuple) {
+            ReteTuple previous = this.first;
+            ReteTuple current = previous;
+            while ( current != null ) {
+                final ReteTuple next = (ReteTuple) current.getNext();
+                if ( tuple.equals( current ) ) {
+                    if ( this.first == current ) {
+                        this.first = next;
+                    } else {
+                        previous.setNext( next );
+                    }
+                    current.setNext( null );
+                    return current;
+                }
+                previous = current;
+                current = next;
+            }
+            return current;
+        }
+
+        public boolean matches(final Object object,
+                               final int objectHashCode) {
+            return this.hashCode == objectHashCode && this.index.equal( object,
+                                                                        this.first );
+        }
+
+        public boolean matches(final ReteTuple tuple,
+                               final int tupleHashCode) {
+            return this.hashCode == tupleHashCode && this.index.equal( this.first,
+                                                                       tuple );
+        }
+
+        public int hashCode() {
+            return this.hashCode;
+        }
+
+        public boolean equals(final Object object) {
+            final FieldIndexEntry other = (FieldIndexEntry) object;
+            return this.hashCode == other.hashCode && this.index == other.index;
+        }
+    }
+
+	@Override
+	public ReteTuple peek() {
+		throw new UnsupportedOperationException( "TupleIndexHashTable does not support  peek()" );
+	}
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/UUID.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/UUID.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/UUID.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,551 @@
+/* JUG Java Uuid Generator
+ *
+ * Copyright (c) 2002- Tatu Saloranta, tatu.saloranta at iki.fi
+ *
+ * Licensed under the License specified in the file LICENSE which is
+ * included with the source code.
+ * You may not use this file except in compliance with the License.
+ *
+ * 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.util;
+
+import java.io.Serializable;
+
+/**
+ * UUID represents Universally Unique Identifiers (aka Global UID in
+ * Windows world). UUIDs are usually generated via UUIDGenerator (or in
+ * case of 'Null UUID', 16 zero bytes, via static method getNullUUID()),
+ * or received from external systems.
+ *
+ * By default class caches the string presentations of UUIDs so that
+ * description is only created the first time it's needed. For memory
+ * stingy applications this caching can be turned off (note though
+ * that if uuid.toString() is never called, desc is never calculated
+ * so only loss is the space allocated for the desc pointer... which
+ * can of course be commented out to save memory).
+ *
+ * Similarly, hash code is calculated when it's needed for the first
+ * time, and from thereon that value is just returned. This means
+ * that using UUIDs as keys should be reasonably efficient.
+ *
+ * UUIDs can be compared for equality, serialized, cloned and even sorted.
+ * Equality is a simple bit-wise comparison. Ordering (for sorting) is done by
+ * first ordering based on type (in the order of numeric values of
+ * types), secondarily by time stamp (only for time-based time stamps),
+ * and finally by straight numeric byte-by-byte comparison (from
+ * most to least significant bytes).
+ */
+
+public class UUID
+    implements
+    Serializable,
+    Cloneable,
+    Comparable {
+    private final static String kHexChars            = "0123456789abcdefABCDEF";
+
+    public final static byte    INDEX_CLOCK_HI       = 6;
+    public final static byte    INDEX_CLOCK_MID      = 4;
+    public final static byte    INDEX_CLOCK_LO       = 0;
+
+    public final static byte    INDEX_TYPE           = 6;
+    // Clock seq. & variant are multiplexed...
+    public final static byte    INDEX_CLOCK_SEQUENCE = 8;
+    public final static byte    INDEX_VARIATION      = 8;
+
+    public final static byte    TYPE_NULL            = 0;
+    public final static byte    TYPE_TIME_BASED      = 1;
+    public final static byte    TYPE_DCE             = 2;                                     // Not used
+    public final static byte    TYPE_NAME_BASED      = 3;
+    public final static byte    TYPE_RANDOM_BASED    = 4;
+
+    /* 'Standard' namespaces defined (suggested) by UUID specs:
+     */
+    public final static String  NAMESPACE_DNS        = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
+    public final static String  NAMESPACE_URL        = "6ba7b811-9dad-11d1-80b4-00c04fd430c8";
+    public final static String  NAMESPACE_OID        = "6ba7b812-9dad-11d1-80b4-00c04fd430c8";
+    public final static String  NAMESPACE_X500       = "6ba7b814-9dad-11d1-80b4-00c04fd430c8";
+
+    /* By default let's cache desc, can be turned off. For hash code
+     * there's no point in turning it off (since the int is already
+     * part of the instance memory allocation); if you want to save
+     * those 4 bytes (or possibly bit more if alignment is bad) just
+     * comment out hash caching.
+     */
+    private static boolean      sDescCaching         = true;
+
+    /**
+     * The shared null UUID. Would be nice to do lazy instantiation, but
+     * if the instance really has to be a singleton, that would mean
+     * class-level locking (synchronized getNullUUID()), which would
+     * be some overhead... So let's just bite the bullet the first time
+     * assuming creation of the null UUID (plus wasted space if it's
+     * not needed) can be ignored.
+     */
+    private final static UUID   sNullUUID            = new UUID();
+
+    private final byte[]        mId                  = new byte[16];
+    // Both string presentation and hash value may be cached...
+    private transient String    mDesc                = null;
+    private transient int       mHashCode            = 0;
+
+    /* *** Object creation: *** */
+
+    /**
+     * Default constructor creates a NIL UUID, one that contains all
+     * zeroes
+     *
+     * Note that the clearing of array is actually unnecessary as
+     * JVMs are required to clear up the allocated arrays by default.
+     */
+    public UUID() {
+        /*
+         for (int i = 0; i < 16; ++i) {
+         mId[i] = (byte)0;
+         }
+         */
+    }
+
+    /**
+     * Constructor for cases where you already have the 16-byte binary
+     * representation of the UUID (for example if you save UUIDs binary
+     * takes less than half of space string representation takes).
+     *
+     * @param data array that contains the binary representation of UUID
+     */
+    public UUID(final byte[] data) {
+        /* Could call the other constructor... and/or use System.arraycopy.
+         * However, it's likely that those would make this slower to use,
+         * and initialization is really simple as is in any case.
+         */
+        for ( int i = 0; i < 16; ++i ) {
+            this.mId[i] = data[i];
+        }
+    }
+
+    /**
+     * Constructor for cases where you already have the binary
+     * representation of the UUID (for example if you save UUIDs binary
+     * takes less than half of space string representation takes) in
+     * a byte array
+     *
+     * @param data array that contains the binary representation of UUID
+     * @param start byte offset where UUID starts
+     */
+    public UUID(final byte[] data,
+                final int start) {
+        for ( int i = 0; i < 16; ++i ) {
+            this.mId[i] = data[start + i];
+        }
+    }
+
+    /**
+     * Protected constructor used by UUIDGenerator
+     *
+     * @param type UUID type
+     * @param data 16 byte UUID contents
+     */
+    UUID(final int type,
+         final byte[] data) {
+        for ( int i = 0; i < 16; ++i ) {
+            this.mId[i] = data[i];
+        }
+        // Type is multiplexed with time_hi:
+        this.mId[UUID.INDEX_TYPE] &= (byte) 0x0F;
+        this.mId[UUID.INDEX_TYPE] |= (byte) (type << 4);
+        // Variant masks first two bits of the clock_seq_hi:
+        this.mId[UUID.INDEX_VARIATION] &= (byte) 0x3F;
+        this.mId[UUID.INDEX_VARIATION] |= (byte) 0x80;
+    }
+
+    /**
+     * Constructor for creating UUIDs from the canonical string
+     * representation
+     *
+     * Note that implementation is optimized for speed, not necessarily
+     * code clarity... Also, since what we get might not be 100% canonical
+     * (see below), let's not yet populate mDesc here.
+     *
+     * @param id String that contains the canonical representation of
+     *   the UUID to build; 36-char string (see UUID specs for details).
+     *   Hex-chars may be in upper-case too; UUID class will always output
+     *   them in lowercase.
+     */
+    public UUID(final String id) throws NumberFormatException {
+        if ( id == null ) {
+            throw new NullPointerException();
+        }
+        if ( id.length() != 36 ) {
+            throw new NumberFormatException( "UUID has to be represented by the standard 36-char representation" );
+        }
+
+        for ( int i = 0, j = 0; i < 36; ++j ) {
+            // Need to bypass hyphens:
+            switch ( i ) {
+                case 8 :
+                case 13 :
+                case 18 :
+                case 23 :
+                    if ( id.charAt( i ) != '-' ) {
+                        throw new NumberFormatException( "UUID has to be represented by the standard 36-char representation" );
+                    }
+                    ++i;
+            }
+            final int index;
+            char c = id.charAt( i );
+
+            if ( c >= '0' && c <= '9' ) {
+                this.mId[j] = (byte) ((c - '0') << 4);
+            } else if ( c >= 'a' && c <= 'f' ) {
+                this.mId[j] = (byte) ((c - 'a' + 10) << 4);
+            } else if ( c >= 'A' && c <= 'F' ) {
+                this.mId[j] = (byte) ((c - 'A' + 10) << 4);
+            } else {
+                throw new NumberFormatException( "Non-hex character '" + c + "'" );
+            }
+
+            c = id.charAt( ++i );
+
+            if ( c >= '0' && c <= '9' ) {
+                this.mId[j] |= (byte) (c - '0');
+            } else if ( c >= 'a' && c <= 'f' ) {
+                this.mId[j] |= (byte) (c - 'a' + 10);
+            } else if ( c >= 'A' && c <= 'F' ) {
+                this.mId[j] |= (byte) (c - 'A' + 10);
+            } else {
+                throw new NumberFormatException( "Non-hex character '" + c + "'" );
+            }
+            ++i;
+        }
+    }
+
+    /**
+     * Default cloning behaviour (bitwise copy) is just fine...
+     *
+     * Could clear out cached string presentation, but there's
+     * probably no point in doing that.
+     */
+    public Object clone() {
+        try {
+            return super.clone();
+        } catch ( final CloneNotSupportedException e ) {
+            // shouldn't happen
+            return null;
+        }
+    }
+
+    /* *** Configuration: *** */
+    public static void setDescCaching(final boolean state) {
+        UUID.sDescCaching = state;
+    }
+
+    /* *** Accessors: *** */
+
+    /**
+     * Accessor for getting the shared null UUID
+     *
+     * @return the shared null UUID
+     */
+    public static UUID getNullUUID() {
+        return UUID.sNullUUID;
+    }
+
+    public boolean isNullUUID() {
+        // Assuming null uuid is usually used for nulls:
+        if ( this == UUID.sNullUUID ) {
+            return true;
+        }
+        // Could also check hash code; null uuid has -1 as hash?
+        final byte[] data = this.mId;
+        int i = this.mId.length;
+        final byte zero = (byte) 0;
+        while ( --i >= 0 ) {
+            if ( data[i] != zero ) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns the UUID type code
+     *
+     * @return UUID type
+     */
+    public int getType() {
+        return (this.mId[UUID.INDEX_TYPE] & 0xFF) >> 4;
+    }
+
+    /**
+     * Returns the UUID as a 16-byte byte array
+     *
+     * @return 16-byte byte array that contains UUID bytes in the network
+     *   byte order
+     */
+    public byte[] asByteArray() {
+        final byte[] result = new byte[16];
+        toByteArray( result );
+        return result;
+    }
+
+    /**
+     * Fills in the 16 bytes (from index pos) of the specified byte array
+     * with the UUID contents.
+     *
+     * @param dst Byte array to fill
+     * @param pos Offset in the array
+     */
+    public void toByteArray(final byte[] dst,
+                            final int pos) {
+        final byte[] src = this.mId;
+        for ( int i = 0; i < 16; ++i ) {
+            dst[pos + i] = src[i];
+        }
+    }
+
+    public void toByteArray(final byte[] dst) {
+        toByteArray( dst,
+                     0 );
+    }
+
+    /**
+     * 'Synonym' for 'asByteArray'
+     */
+    public byte[] toByteArray() {
+        return asByteArray();
+    }
+
+    /* *** Standard methods from Object overridden: *** */
+
+    /**
+     * Could use just the default hash code, but we can probably create
+     * a better identity hash (ie. same contents generate same hash)
+     * manually, without sacrificing speed too much. Although multiplications
+     * with modulos would generate better hashing, let's use just shifts,
+     * and do 2 bytes at a time.
+     *<p>
+     * Of course, assuming UUIDs are randomized enough, even simpler
+     * approach might be good enough?
+     *<p>
+     * Is this a good hash? ... one of these days I better read more about
+     * basic hashing techniques I swear!
+     */
+    private final static int[] kShifts = {3, 7, 17, 21, 29, 4, 9};
+
+    public int hashCode() {
+        if ( this.mHashCode == 0 ) {
+            // Let's handle first and last byte separately:
+            int result = this.mId[0] & 0xFF;
+
+            result |= (result << 16);
+            result |= (result << 8);
+
+            for ( int i = 1; i < 15; i += 2 ) {
+                final int curr = (this.mId[i] & 0xFF) << 8 | (this.mId[i + 1] & 0xFF);
+                final int shift = UUID.kShifts[i >> 1];
+
+                if ( shift > 16 ) {
+                    result ^= (curr << shift) | (curr >>> (32 - shift));
+                } else {
+                    result ^= (curr << shift);
+                }
+            }
+
+            // and then the last byte:
+            final int last = this.mId[15] & 0xFF;
+            result ^= (last << 3);
+            result ^= (last << 13);
+
+            result ^= (last << 27);
+            // Let's not accept hash 0 as it indicates 'not hashed yet':
+            if ( result == 0 ) {
+                this.mHashCode = -1;
+            } else {
+                this.mHashCode = result;
+            }
+        }
+        return this.mHashCode;
+    }
+
+    public String toString() {
+        /* Could be synchronized, but there isn't much harm in just taking
+         * our chances (ie. in the worst case we'll form the string more
+         * than once... but result is the same)
+         */
+
+        if ( this.mDesc == null ) {
+            final StringBuffer b = new StringBuffer( 36 );
+
+            for ( int i = 0; i < 16; ++i ) {
+                // Need to bypass hyphens:
+                switch ( i ) {
+                    case 4 :
+                    case 6 :
+                    case 8 :
+                    case 10 :
+                        b.append( '-' );
+                }
+                final int hex = this.mId[i] & 0xFF;
+                b.append( UUID.kHexChars.charAt( hex >> 4 ) );
+                b.append( UUID.kHexChars.charAt( hex & 0x0f ) );
+            }
+            if ( !UUID.sDescCaching ) {
+                return b.toString();
+            }
+            this.mDesc = b.toString();
+        }
+        return this.mDesc;
+    }
+
+    /* *** Comparison methods: *** */
+
+    private final static int[] sTimeCompare = new int[]{UUID.INDEX_CLOCK_HI, UUID.INDEX_CLOCK_HI + 1, UUID.INDEX_CLOCK_MID, UUID.INDEX_CLOCK_MID + 1, UUID.INDEX_CLOCK_LO, UUID.INDEX_CLOCK_LO + 1, UUID.INDEX_CLOCK_LO + 2, UUID.INDEX_CLOCK_LO + 3,};
+
+    /**
+     * Let's also make UUIDs sortable. This will mostly/only be useful with
+     * time-based UUIDs; they will sorted by time of creation. The order
+     * will be strictly correct with UUIDs produced over one JVM's lifetime;
+     * that is, if more than one JVMs create UUIDs and/or system is rebooted
+     * the order may not be 100% accurate between UUIDs created under
+     * different JVMs.
+     *
+     * For all UUIDs, type is first compared, and UUIDs of different types
+     * are sorted together (ie. null UUID is before all other UUIDs, then
+     * time-based UUIDs etc). If types are the same, time-based UUIDs'
+     * time stamps (including additional clock counter) are compared, so
+     * UUIDs created first are ordered first. For all other types (and for
+     * time-based UUIDs with same time stamp, which should only occur
+     * when comparing a UUID with itself, or with UUIDs created on
+     * different JVMs or external systems) binary comparison is done
+     * over all 16 bytes.
+     *
+     * @param o Object to compare this UUID to; should be a UUID
+     *
+     * @return -1 if this UUID should be ordered before the one passed,
+     *   1 if after, and 0 if they are the same
+     *
+     * @throws ClassCastException if o is not a UUID.
+     */
+    public int compareTo(final Object o) {
+        final UUID other = (UUID) o;
+
+        final int thisType = getType();
+        final int thatType = other.getType();
+
+        /* Let's first order by type:
+         */
+        if ( thisType > thatType ) {
+            return 1;
+        } else if ( thisType < thatType ) {
+            return -1;
+        }
+
+        /* And for time-based UUIDs let's compare time stamps first,
+         * then the rest... For all other types, we'll just do straight
+         * byte-by-byte comparison.
+         */
+        final byte[] thisId = this.mId;
+        final byte[] thatId = other.mId;
+        int i = 0;
+        if ( thisType == UUID.TYPE_TIME_BASED ) {
+            for ( ; i < 8; ++i ) {
+                final int index = UUID.sTimeCompare[i];
+                final int cmp = ((thisId[index]) & 0xFF) - ((thatId[index]) & 0xFF);
+                if ( cmp != 0 ) {
+                    return cmp;
+                }
+            }
+            // Let's fall down to full comparison otherwise
+        }
+
+        for ( ; i < 16; ++i ) {
+            final int cmp = ((thisId[i]) & 0xFF) - ((thatId[i]) & 0xFF);
+            if ( cmp != 0 ) {
+                return cmp;
+            }
+        }
+
+        return 0;
+    }
+
+    /**
+     * Checking equality of UUIDs is easy; just compare the 128-bit
+     * number.
+     */
+    public boolean equals(final Object o) {
+        if ( !(o instanceof UUID) ) {
+            return false;
+        }
+        final byte[] otherId = ((UUID) o).mId;
+        final byte[] thisId = this.mId;
+        for ( int i = 0; i < 16; ++i ) {
+            if ( otherId[i] != thisId[i] ) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Constructs a new UUID instance given the canonical string
+     * representation of an UUID.
+     *
+     * Note that calling this method returns the same result as would
+     * using the matching (1 string arg) constructor.
+     *
+     * @param id Canonical string representation used for constructing
+     *  an UUID instance
+     *
+     * @throws NumberFormatException if 'id' is invalid UUID
+     */
+    public static UUID valueOf(final String id) throws NumberFormatException {
+        return new UUID( id );
+    }
+
+    /**
+     * Constructs a new UUID instance given a byte array that contains
+     * the (16 byte) binary representation.
+     *
+     * Note that calling this method returns the same result as would
+     * using the matching constructor
+     *
+     * @param src Byte array that contains the UUID definition
+     * @param start Offset in the array where the UUID starts
+     */
+    public static UUID valueOf(final byte[] src,
+                               final int start) {
+        return new UUID( src,
+                         start );
+    }
+
+    /**
+     * Constructs a new UUID instance given a byte array that contains
+     * the (16 byte) binary representation.
+     *
+     * Note that calling this method returns the same result as would
+     * using the matching constructor
+     *
+     * @param src Byte array that contains the UUID definition
+     */
+    public static UUID valueOf(final byte[] src) {
+        return new UUID( src );
+    }
+
+    private void copyFrom(final UUID src) {
+        final byte[] srcB = src.mId;
+        final byte[] dstB = this.mId;
+
+        for ( int i = 0; i < 16; ++i ) {
+            dstB[i] = srcB[i];
+        }
+
+        this.mDesc = UUID.sDescCaching ? src.mDesc : null;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/UUIDGenerator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/UUIDGenerator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/UUIDGenerator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,165 @@
+/* JUG Java Uuid Generator
+ *
+ * Copyright (c) 2002- Tatu Saloranta, tatu.saloranta at iki.fi
+ *
+ * Licensed under the License specified in the file LICENSE which is
+ * included with the source code.
+ * You may not use this file except in compliance with the License.
+ *
+ * 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.util;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Random;
+
+/**
+ * Ripped from JUG
+ * 
+ * @see org.safehaus.jug
+ */
+public final class UUIDGenerator {
+    private final static UUIDGenerator sSingleton = new UUIDGenerator();
+
+    /**
+     * Random-generator, used by various UUID-generation methods:
+     */
+    private Random                     mRnd       = null;
+
+    /**
+     * MD5 hasher for name-based digests:
+     */
+    private MessageDigest              mHasher    = null;
+
+    /*
+     /////////////////////////////////////////////////////
+     // Life-cycle
+     /////////////////////////////////////////////////////
+     */
+
+    /**
+     * Constructor is private to enforce singleton access.
+     */
+    private UUIDGenerator() {
+    }
+
+    /**
+     * Method used for accessing the singleton generator instance.
+     */
+    public static UUIDGenerator getInstance() {
+        return UUIDGenerator.sSingleton;
+    }
+
+    /*
+     /////////////////////////////////////////////////////
+     // Configuration
+     /////////////////////////////////////////////////////
+     */
+
+    /**
+     * Method for getting the shared random number generator used for
+     * generating the UUIDs. This way the initialization cost is only
+     * taken once; access need not be synchronized (or in cases where
+     * it has to, SecureRandom takes care of it); it might even be good
+     * for getting really 'random' stuff to get shared access...
+     */
+    public Random getRandomNumberGenerator() {
+        /* Could be synchronized, but since side effects are trivial
+         * (ie. possibility of generating more than one SecureRandom,
+         * of which all but one are dumped) let's not add synchronization
+         * overhead:
+         */
+        if ( this.mRnd == null ) {
+            this.mRnd = new SecureRandom();
+        }
+        return this.mRnd;
+    }
+
+    /**
+     * Method that can  be called to specify alternative random
+     * number generator to use. This is usually done to use
+     * implementation that is faster than
+     * {@link SecureRandom} that is used by default.
+     *<p>
+     * Note that to avoid first-time initialization penalty
+     * of using {@link SecureRandom}, this method has to be called
+     * before generating the first random-number based UUID.
+     */
+    public void setRandomNumberGenerator(final Random r) {
+        this.mRnd = r;
+    }
+
+    /* Method for getting the shared message digest (hash) algorithm.
+     * Whether to use the shared one or not depends; using shared instance
+     * adds synchronization overhead (access has to be sync'ed), but
+     * using multiple separate digests wastes memory.
+     */
+    public MessageDigest getHashAlgorithm() {
+        /* Similar to the shared random number generator, it's not necessary
+         * to synchronize initialization. However, use of the hash instance
+         * HAS to be synchronized by the caller to prevent problems with
+         * multiple threads updating digest etc.
+         */
+        if ( this.mHasher == null ) {
+            try {
+                this.mHasher = MessageDigest.getInstance( "MD5" );
+            } catch ( final NoSuchAlgorithmException nex ) {
+                throw new Error( "Couldn't instantiate an MD5 MessageDigest instance: " + nex.toString() );
+            }
+        }
+        return this.mHasher;
+    }
+
+    /*
+     /////////////////////////////////////////////////////
+     // UUID generation methods
+     /////////////////////////////////////////////////////
+     */
+
+    /**
+     * Method for generating (pseudo-)random based UUIDs, using the
+     * default (shared) SecureRandom object.
+     * 
+     * Note that the first time
+     * SecureRandom object is used, there is noticeable delay between
+     * calling the method and getting the reply. This is because SecureRandom
+     * has to initialize itself to reasonably random state. Thus, if you
+     * want to lessen delay, it may be be a good idea to either get the
+     * first random UUID asynchronously from a separate thread, or to
+     * use the other generateRandomBasedUUID passing a previously initialized
+     * SecureRandom instance.
+     *
+     * @return UUID generated using (pseudo-)random based method
+     */
+    public UUID generateRandomBasedUUID() {
+        return generateRandomBasedUUID( getRandomNumberGenerator() );
+    }
+
+    /**
+     * Method for generating (pseudo-)random based UUIDs, using the
+     * specified  SecureRandom object. To prevent/avoid delay JDK's
+     * default SecureRandom object causes when first random number
+     * is generated, it may be a good idea to initialize the SecureRandom
+     * instance (on a separate thread for example) when app starts.
+     * 
+     * @param randomGenerator Random number generator to use for getting the
+     *   random number from which UUID will be composed.
+     *
+     * @return UUID generated using (pseudo-)random based method
+     */
+    public UUID generateRandomBasedUUID(final Random randomGenerator) {
+        final byte[] rnd = new byte[16];
+
+        randomGenerator.nextBytes( rnd );
+
+        return new UUID( UUID.TYPE_RANDOM_BASED,
+                         rnd );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/asm/ClassFieldInspector.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/asm/ClassFieldInspector.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/asm/ClassFieldInspector.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,378 @@
+package org.drools.util.asm;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.beans.Introspector;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.drools.asm.AnnotationVisitor;
+import org.drools.asm.Attribute;
+import org.drools.asm.ClassReader;
+import org.drools.asm.ClassVisitor;
+import org.drools.asm.FieldVisitor;
+import org.drools.asm.MethodVisitor;
+import org.drools.asm.Opcodes;
+
+/**
+ * Visit a POJO user class, and extract the property getter methods that are public, in the 
+ * order in which they are declared actually in the class itself (not using introspection).
+ * 
+ * This may be enhanced in the future to allow annotations or perhaps external meta data
+ * configure the order of the indexes, as this may provide fine tuning options in special cases.
+ * 
+ * @author Michael Neale
+ */
+public class ClassFieldInspector {
+
+    private final List methods     = new ArrayList();
+    private final Map  fieldNames  = new HashMap();
+    private final Map  fieldTypes  = new HashMap();
+    private final Map  methodNames = new HashMap();
+    private final Set  nonGetters  = new HashSet();
+
+    /**
+     * @param clazz The class that the fields to be shadowed are extracted for.
+     * @throws IOException
+     */
+    public ClassFieldInspector(final Class clazz) throws IOException {
+        this( clazz,
+              true );
+    }
+
+    public ClassFieldInspector(final Class clazz,
+                               final boolean includeFinalMethods) throws IOException {
+        final String name = getResourcePath( clazz );
+        final InputStream stream = clazz.getResourceAsStream( name );
+
+        if ( stream != null ) {
+            processClassWithByteCode( clazz,
+                                      stream,
+                                      includeFinalMethods );
+        } else {
+            processClassWithoutByteCode( clazz,
+                                         includeFinalMethods );
+        }
+    }
+
+    /** Walk up the inheritance hierarchy recursively, reading in fields */
+    private void processClassWithByteCode(final Class clazz,
+                                          final InputStream stream,
+                                          final boolean includeFinalMethods) throws IOException {
+
+        final ClassReader reader = new ClassReader( stream );
+        final ClassFieldVisitor visitor = new ClassFieldVisitor( clazz,
+                                                                 includeFinalMethods,
+                                                                 this );
+        reader.accept( visitor,
+                       false );
+        if ( clazz.getSuperclass() != null ) {
+            final String name = getResourcePath( clazz.getSuperclass() );
+            final InputStream parentStream = clazz.getResourceAsStream( name );
+            if ( parentStream != null ) {
+                processClassWithByteCode( clazz.getSuperclass(),
+                                          parentStream,
+                                          includeFinalMethods );
+            } else {
+                processClassWithoutByteCode( clazz.getSuperclass(),
+                                             includeFinalMethods );
+            }
+        }
+        if ( clazz.isInterface() ) {
+            final Class[] interfaces = clazz.getInterfaces();
+            for ( int i = 0; i < interfaces.length; i++ ) {
+                final String name = getResourcePath( interfaces[i] );
+                final InputStream parentStream = clazz.getResourceAsStream( name );
+                if ( parentStream != null ) {
+                    processClassWithByteCode( interfaces[i],
+                                              parentStream,
+                                              includeFinalMethods );
+                } else {
+                    processClassWithoutByteCode( interfaces[i],
+                                                 includeFinalMethods );
+                }
+            }
+        }
+    }
+
+    private void processClassWithoutByteCode(final Class clazz,
+                                             final boolean includeFinalMethods) {
+        final Method[] methods = clazz.getMethods();
+        for ( int i = 0; i < methods.length; i++ ) {
+
+            //only want public methods that start with 'get' or 'is'
+            //and have no args, and return a value
+            final int mask = includeFinalMethods ? Modifier.PUBLIC : Modifier.PUBLIC | Modifier.FINAL;
+            if ( ((methods[i].getModifiers() & mask) == Modifier.PUBLIC) && (methods[i].getParameterTypes().length == 0) && (!methods[i].getName().equals( "<init>" )) &&
+                 ( !methods[i].getName().equals( "<clinit>" )) && 
+                 (methods[i].getReturnType() != void.class) ) {
+                final int fieldIndex = this.methods.size();
+                addToMapping( methods[i],
+                              fieldIndex );
+            }
+        }
+    }
+
+    /**
+     * Convert it to a form so we can load the bytes from the classpath.
+     */
+    private String getResourcePath(final Class clazz) {
+        return "/" + clazz.getName().replace( '.',
+                                              '/' ) + ".class";
+    }
+
+    /** 
+     * Return a list in order of which the getters (and "is") methods were found.
+     * This should only be done once when compiling a rulebase ideally.
+     */
+    public List getPropertyGetters() {
+        return this.methods;
+    }
+
+    /**
+     * Return a mapping of the field "names" (ie bean property name convention)
+     * to the numerical index by which they can be accessed.
+     */
+    public Map getFieldNames() {
+        return this.fieldNames;
+    }
+
+    /**
+     * @return A mapping of field types (unboxed).
+     */
+    public Map getFieldTypes() {
+        return this.fieldTypes;
+    }
+
+    /** 
+     * @return A mapping of methods for the getters. 
+     */
+    public Map getGetterMethods() {
+        return this.methodNames;
+    }
+
+    private void addToMapping(final Method method,
+                              final int index) {
+        final String name = method.getName();
+        int offset;
+        if ( name.startsWith( "is" ) ) {
+            offset = 2;
+        } else if ( name.startsWith( "get" ) ) {
+            offset = 3;
+        } else {
+            offset = 0;
+        }
+        final String fieldName = calcFieldName( name,
+                                                offset );
+        if ( this.fieldNames.containsKey( fieldName ) ) {
+            //only want it once, the first one thats found
+            if ( offset != 0 && this.nonGetters.contains( fieldName ) ) {
+                //replace the non getter method with the getter one
+                removeOldField( fieldName );
+                storeField( method,
+                            index,
+                            fieldName );
+                this.nonGetters.remove( fieldName );
+            }
+        } else {
+            storeField( method,
+                        index,
+                        fieldName );
+            if ( offset == 0 ) {
+                this.nonGetters.add( fieldName );
+            }
+        }
+    }
+
+    private void removeOldField(final String fieldName) {
+        this.fieldNames.remove( fieldName );
+        this.fieldTypes.remove( fieldName );
+        this.methods.remove( this.methodNames.get( fieldName ) );
+        this.methodNames.remove( fieldName );
+
+    }
+
+    private void storeField(final Method method,
+                            final int index,
+                            final String fieldName) {
+        this.fieldNames.put( fieldName,
+                             new Integer( index ) );
+        this.fieldTypes.put( fieldName,
+                             method.getReturnType() );
+        this.methodNames.put( fieldName,
+                              method );
+        this.methods.add( method );
+    }
+
+    private String calcFieldName(String name,
+                                 final int offset) {
+        name = name.substring( offset );
+        return Introspector.decapitalize( name );
+    }
+
+    /**
+     * Using the ASM classfield extractor to pluck it out in the order they appear in the class file.
+     * @author Michael Neale
+     */
+    static class ClassFieldVisitor
+        implements
+        ClassVisitor {
+
+        private Class               clazz;
+        private ClassFieldInspector inspector;
+        private boolean             includeFinalMethods;
+
+        ClassFieldVisitor(final Class cls,
+                          final boolean includeFinalMethods,
+                          final ClassFieldInspector inspector) {
+            this.clazz = cls;
+            this.includeFinalMethods = includeFinalMethods;
+            this.inspector = inspector;
+        }
+
+        public MethodVisitor visitMethod(final int access,
+                                         final String name,
+                                         final String desc,
+                                         final String signature,
+                                         final String[] exceptions) {
+            //only want public methods
+            //and have no args, and return a value
+            final int mask = this.includeFinalMethods ? Opcodes.ACC_PUBLIC : Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL;
+            if ( (access & mask) == Opcodes.ACC_PUBLIC ) {
+                if ( desc.startsWith( "()" ) && (!name.equals( "<init>" )) &&
+                 ( ! name.equals( "<clinit>" ) ) ) {// && ( name.startsWith("get") || name.startsWith("is") ) ) {
+                    try {
+                        final Method method = this.clazz.getMethod( name,
+                                                                    (Class[]) null );
+                        if ( method.getReturnType() != void.class ) {
+                            final int fieldIndex = this.inspector.methods.size();
+                            this.inspector.addToMapping( method,
+                                                         fieldIndex );
+                        }
+                    } catch ( final NoSuchMethodException e ) {
+                        throw new IllegalStateException( "Error in getting field access method." );
+                    }
+                }
+            }
+            return null;
+        }
+
+        public void visit(final int arg0,
+                          final int arg1,
+                          final String arg2,
+                          final String arg3,
+                          final String[] arg4,
+                          final String arg5) {
+        }
+
+        public void visitInnerClass(final String arg0,
+                                    final String arg1,
+                                    final String arg2,
+                                    final int arg3) {
+        }
+
+        public void visitField(final int access,
+                               final String arg1,
+                               final String arg2,
+                               final Object arg3,
+                               final Attribute arg4) {
+        }
+
+        public void visitAttribute(final Attribute arg0) {
+        }
+
+        public void visitEnd() {
+        }
+
+        public void visit(final int arg0,
+                          final int arg1,
+                          final String arg2,
+                          final String arg3,
+                          final String arg4,
+                          final String[] arg5) {
+
+        }
+
+        public void visitSource(final String arg0,
+                                final String arg1) {
+
+        }
+
+        public void visitOuterClass(final String arg0,
+                                    final String arg1,
+                                    final String arg2) {
+
+        }
+
+        public AnnotationVisitor visitAnnotation(final String arg0,
+                                                 final boolean arg1) {
+
+            return new ClassFieldAnnotationVisitor();
+        }
+
+        public FieldVisitor visitField(final int arg0,
+                                       final String arg1,
+                                       final String arg2,
+                                       final String arg3,
+                                       final Object arg4) {
+
+            return null;
+        }
+
+    }
+
+    /** 
+     * This is required for POJOs that have annotations. 
+     * It may also come in handy if we want to allow custom annotations for marking field numbers etc.
+     */
+    static class ClassFieldAnnotationVisitor
+        implements
+        AnnotationVisitor {
+
+        public void visit(final String arg0,
+                          final Object arg1) {
+        }
+
+        public void visitEnum(final String arg0,
+                              final String arg1,
+                              final String arg2) {
+        }
+
+        public AnnotationVisitor visitAnnotation(final String arg0,
+                                                 final String arg1) {
+            return new ClassFieldAnnotationVisitor();
+        }
+
+        public AnnotationVisitor visitArray(final String arg0) {
+            return new ClassFieldAnnotationVisitor();
+        }
+
+        public void visitEnd() {
+
+        }
+
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/asm/FieldAccessor.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/asm/FieldAccessor.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/asm/FieldAccessor.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,45 @@
+package org.drools.util.asm;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+/**
+ * This provides "field" access to getters on a given class.
+ * Implementations are generated into byte code (using a switchtable) 
+ * when a new class is encountered.
+ * @deprecated use ClassFieldExtractor instead
+ * @author Michael Neale
+ * @author "Jeff Brown" <brown_j at ociweb.com>
+ */
+public interface FieldAccessor
+    extends
+    Serializable {
+
+    /**
+     * Returns the "field" corresponding to the order in which it is in the object (class).
+     * 
+     * @param obj The object for the field to be extracted from.
+     * @param idx The index of the "field". Refer to FieldAccessorMap to get the mapping
+     * of the names of the "fields" to the index value to use for fast lookup.
+     * 
+     * @return Appropriate return type. Primitives are boxed to the corresponding type.
+     */
+    public Object getFieldByIndex(Object obj,
+                                  int idx);
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/asm/FieldAccessorMap.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/asm/FieldAccessorMap.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/asm/FieldAccessorMap.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,60 @@
+package org.drools.util.asm;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Map;
+
+/**
+ * This class holds a dynamically generated instance of a FieldAccessor, 
+ * and a map of the field names to index numbers that are used to access the fields. 
+ * @deprecated use ClassFiledExtractor instead.
+ * @author Michael Neale
+ */
+public class FieldAccessorMap {
+
+    private final FieldAccessor accessor;
+    private final Map           nameMap;
+
+    /**
+     * @param accessor
+     * @param fieldAccessMethods Will be used to calculate the "field name"
+     * which is really like bean property names.
+     */
+    FieldAccessorMap(final FieldAccessor accessor,
+                     final Map nameMap) {
+        this.accessor = accessor;
+        this.nameMap = nameMap;
+    }
+
+    /**
+     * @return A map of field names, to their index value, for use by the accessor. 
+     */
+    public Map getFieldNameMap() {
+        return this.nameMap;
+    }
+
+    /**
+     * @return The field index accessor itself.
+     */
+    public FieldAccessor getFieldAccessor() {
+        return this.accessor;
+    }
+
+    public int getIndex(final String name) {
+        return ((Integer) this.nameMap.get( name )).intValue();
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/asm/MethodComparator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/asm/MethodComparator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/util/asm/MethodComparator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,186 @@
+package org.drools.util.asm;
+
+import java.util.List;
+
+import org.drools.asm.AnnotationVisitor;
+import org.drools.asm.Attribute;
+import org.drools.asm.ClassReader;
+import org.drools.asm.ClassVisitor;
+import org.drools.asm.FieldVisitor;
+import org.drools.asm.MethodVisitor;
+import org.drools.asm.util.TraceMethodVisitor;
+
+/**
+ * The purpose of this utility it to check if 2 method implementations are equivalent, by comparing the bytecode.
+ * This essentual for node sharing where java semantics are involved.
+ * @author Michael Neale
+ */
+public class MethodComparator {
+
+    /**
+     * This actually does the comparing.
+     * Class1 and Class2 are class reader instances to the respective classes. method1 and method2 are looked up on the 
+     * respective classes and their contents compared.
+     * 
+     * This is a convenience method.
+     */
+    public boolean equivalent(final String method1,
+                              final ClassReader class1,
+                              final String method2,
+                              final ClassReader class2) {
+
+        final List list1 = getMethodBytecode( method1,
+                                              class1 );
+        final List list2 = getMethodBytecode( method2,
+                                              class2 );
+
+        return compareBytecode( list1,
+                                list2 );
+    }
+
+    /**
+     * This will return a series of bytecode instructions which can be used to compare one method with another.
+     * debug info like local var declarations and line numbers are ignored, so the focus is on the content.
+     */
+    public List getMethodBytecode(final String methodName,
+                                  final ClassReader classReader) {
+        final Tracer visit = new Tracer( methodName );
+        classReader.accept( visit,
+                            true );
+        final TraceMethodVisitor trace = visit.getTrace();
+        return trace.getText();
+    }
+
+    /**
+     * This will return a series of bytecode instructions which can be used to compare one method with another.
+     * debug info like local var declarations and line numbers are ignored, so the focus is on the content.
+     */
+    public static List getMethodBytecode(final String methodName,
+                                         final byte[] bytes) {
+        final Tracer visit = new Tracer( methodName );
+        final ClassReader classReader = new ClassReader( bytes );
+        classReader.accept( visit,
+                            true );
+        final TraceMethodVisitor trace = visit.getTrace();
+        return trace.getText();
+    }
+
+    /**
+     * Compares 2 bytecode listings.
+     * Returns true if they are identical.
+     */
+    public static boolean compareBytecode(final List b1,
+                                          final List b2) {
+        if ( b1.size() != b2.size() ) {
+            return false;
+        }
+
+        for ( int i = 0; i < b1.size(); i++ ) {
+            if ( !(b1.get( i ).equals( b2.get( i ) )) ) {
+                return false;
+
+            }
+        }
+        return true;
+    }
+
+    public static class Tracer
+        implements
+        ClassVisitor {
+
+        private TraceMethodVisitor trace;
+        private String             methodName;
+
+        public Tracer(final String methodName) {
+            this.methodName = methodName;
+        }
+
+        public void visit(final int version,
+                          final int access,
+                          final String name,
+                          final String signature,
+                          final String superName,
+                          final String[] interfaces) {
+        }
+
+        public AnnotationVisitor visitAnnotation(final String desc,
+                                                 final boolean visible) {
+            return new DummyAnnotationVisitor();
+        }
+
+        public void visitAttribute(final Attribute attr) {
+        }
+
+        public void visitEnd() {
+        }
+
+        public FieldVisitor visitField(final int access,
+                                       final String name,
+                                       final String desc,
+                                       final String signature,
+                                       final Object value) {
+            return null;
+        }
+
+        public void visitInnerClass(final String name,
+                                    final String outerName,
+                                    final String innerName,
+                                    final int access) {
+        }
+
+        public MethodVisitor visitMethod(final int access,
+                                         final String name,
+                                         final String desc,
+                                         final String signature,
+                                         final String[] exceptions) {
+
+            if ( this.methodName.equals( name ) ) {
+                this.trace = new TraceMethodVisitor();
+                return this.trace;
+            }
+            return null;
+        }
+
+        public void visitOuterClass(final String owner,
+                                    final String name,
+                                    final String desc) {
+        }
+
+        public void visitSource(final String source,
+                                final String debug) {
+        }
+
+        public TraceMethodVisitor getTrace() {
+            return this.trace;
+        }
+
+    }
+
+    static class DummyAnnotationVisitor
+        implements
+        AnnotationVisitor {
+
+        public void visit(final String name,
+                          final Object value) {
+        }
+
+        public AnnotationVisitor visitAnnotation(final String name,
+                                                 final String desc) {
+            return new DummyAnnotationVisitor();
+        }
+
+        public AnnotationVisitor visitArray(final String name) {
+            return new DummyAnnotationVisitor();
+        }
+
+        public void visitEnd() {
+        }
+
+        public void visitEnum(final String name,
+                              final String desc,
+                              final String value) {
+        }
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/Connection.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/Connection.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/Connection.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,52 @@
+package org.drools.workflow.core;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Represents a connection between two nodes in a workflow. 
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface Connection {
+
+    /**
+     * Returns the from node of the connection.
+     * @return the from node of the connection.
+     */
+    Node getFrom();
+
+    /**
+     * Returns the to node of the connection
+     * @return the to node of the connection
+     */
+    Node getTo();
+
+    /**
+     * Returns the type of the connection at the from node
+     * 
+     * @return the type of the connection at the from node
+     */
+    String getFromType();
+
+    /**
+     * Returns the type of the connection at the to node
+     * 
+     * @return the type of the connection at the to node
+     */
+    String getToType();
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/Constraint.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/Constraint.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/Constraint.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,97 @@
+package org.drools.workflow.core;
+
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Represents a constraint in a RuleFlow.
+ * Can be used to specify conditions in (X)OR-splits. 
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface Constraint {
+    /**
+     * Typically this method returns the constraint as a String
+     * @return the constraint
+     */
+    String getConstraint();
+
+    /**
+     * Method for setting the constraint
+     * @param constraint 	the constraint
+     */
+    void setConstraint(String constraint);
+
+    /**
+     * Returns the name of the constraint
+     * @return the name of the constraint
+     */
+    String getName();
+
+    /**
+     * Sets the name of the constraint
+     * @param name	the name of the constraint
+     */
+    void setName(String name);
+
+    /**
+     * Returns the priority of the constraint
+     * 
+     * @return the priority of the constraint
+     */
+    int getPriority();
+
+    /**
+     * Method for setting the priority of the constraint
+     * 
+     * @param priority	the priority of the constraint
+     */
+    void setPriority(int priority);
+
+    /**
+     * Returns the type of the constraint,
+     * e.g. "code" or "rule"
+     * 
+     * @return the type of the constraint
+     */
+    String getType();
+
+    /**
+     * Method for setting the type of the constraint,
+     * e.g. "code" or "rule"
+     * 
+     * @param type  the type of the constraint
+     */
+    void setType(String type);
+
+    /**
+     * Returns the dialect of the constraint,
+     * e.g. "mvel" or "java"
+     * 
+     * @return the dialect of the constraint
+     */
+    String getDialect();
+
+    /**
+     * Method for setting the dialect of the constraint,
+     * e.g. "mvel" or "java"
+     * 
+     * @param type  the dialect of the constraint
+     */
+    void setDialect(String dialect);
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/Node.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/Node.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/Node.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,89 @@
+package org.drools.workflow.core;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Represents a node in a RuleFlow. 
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface Node extends Serializable {
+
+    static final String CONNECTION_DEFAULT_TYPE = "DROOLS_DEFAULT";
+    
+    /**
+     * Returns the id of the node
+     * 
+     * @return the id of the node
+     */
+    long getId();
+
+    /**
+     * Method for setting the id of the node
+     * 
+     * @param id	the id of the node
+     */
+    void setId(long id);
+
+    /**
+     * Returns the name of the node
+     * 
+     * @return the name of the node
+     */
+    String getName();
+
+    /**
+     * Method for setting the name of the node
+     * 
+     * @param name 	the name of the node
+     */
+    void setName(String name);
+
+    /**
+     * Returns the incoming connections
+     * 
+     * @return the incoming connections 
+     */
+    Map<String, List<Connection>> getIncomingConnections();
+
+    /**
+     * Returns the outgoing connections
+     * 
+     * @return the outgoing connections 
+     */
+    Map<String, List<Connection>> getOutgoingConnections();
+
+    void addIncomingConnection(String type, Connection connection);
+    
+    void addOutgoingConnection(String type, Connection connection);
+    
+    void removeIncomingConnection(String type, Connection connection);
+    
+    void removeOutgoingConnection(String type, Connection connection);
+    
+    List<Connection> getIncomingConnections(String type);
+    
+    List<Connection> getOutgoingConnections(String type);
+    
+    NodeContainer getNodeContainer();
+    
+    void setNodeContainer(NodeContainer nodeContainer);
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/NodeContainer.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/NodeContainer.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/NodeContainer.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,44 @@
+package org.drools.workflow.core;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface NodeContainer {
+
+    /**
+     * Returns the nodes of this node container.
+     * 
+     * @return the nodes of this node container
+     */
+    Node[] getNodes();
+
+    /**
+     * Returns the node with the given id
+     * 
+     * @param id
+     *            the node id
+     * @return the node with the given id
+     * @throws IllegalArgumentException
+     *             if an unknown id is passed
+     */
+    Node getNode(long id);
+
+    /**
+     * Method for adding a node to this node container. 
+     * Note that the node will get an id unique for this node container.
+     * 
+     * @param node  the node to be added
+     * @throws IllegalArgumentException if <code>node</code> is null 
+     */
+    void addNode(Node node);
+
+    /**
+     * Method for removing a node from this node container
+     * 
+     * @param node  the node to be removed
+     * @throws IllegalArgumentException if <code>node</code> is null or unknown
+     */
+    void removeNode(Node node);
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/WorkflowProcess.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/WorkflowProcess.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/WorkflowProcess.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,68 @@
+package org.drools.workflow.core;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.List;
+import java.util.Map;
+
+import org.drools.process.core.Process;
+
+/**
+ * Represents a RuleFlow process. 
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface WorkflowProcess extends Process, NodeContainer {
+
+    /**
+     * Returns the imports of this RuleFlow process.
+     * They are defined as a List of fully qualified class names.
+     * 
+     * @return	the imports of this RuleFlow process
+     */
+    List<String> getImports();
+    
+    /**
+     * Sets the imports of this RuleFlow process
+     * 
+     * @param imports	the imports as a List of fully qualified class names
+     */
+    void setImports(List<String> imports);
+
+    /**
+     * Returns the globals of this RuleFlow process.
+     * They are defined as a Map with the name as key and the type as value.
+     * 
+     * @return	the imports of this RuleFlow process
+     */
+    Map<String, String> getGlobals();
+    
+    /**
+     * Sets the imports of this RuleFlow process
+     * 
+     * @param imports	the globals as a Map with the name as key and the type as value
+     */
+    void setGlobals(Map<String, String> globals);
+
+    /**
+     * Returns the names of the globals used in this RuleFlow process
+     * 
+     * @return	the names of the globals of this RuleFlow process
+     */
+    String[] getGlobalNames();
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/ConnectionImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/ConnectionImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/ConnectionImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,114 @@
+package org.drools.workflow.core.impl;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.drools.workflow.core.Connection;
+import org.drools.workflow.core.Node;
+
+/**
+ * Default implementation of a connection.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class ConnectionImpl implements Connection, Serializable {
+
+    private static final long serialVersionUID = 400L;
+
+    private Node from;
+    private Node to;
+    private String fromType;
+    private String toType;
+    
+    ConnectionImpl() {
+    }
+
+    /**
+     * Creates a new connection, given a from node, a to node 
+     * and a type.
+     * 
+     * @param from      The from node
+     * @param to        The to node
+     * @param type      The connection type
+     */
+    public ConnectionImpl(final Node from, final String fromType,
+                          final Node to, final String toType) {
+        if (from == null) {
+            throw new IllegalArgumentException("From node is null!");
+        }
+        if (fromType == null) {
+            throw new IllegalArgumentException("From type is null!");
+        }
+        if (to == null) {
+            throw new IllegalArgumentException("To node is null!");
+        }
+        if (toType == null) {
+            throw new IllegalArgumentException("To type is null!");
+        }
+        if (from.equals(to)) {
+            throw new IllegalArgumentException(
+                "To and from nodes are the same!");
+        }
+        this.from = from;
+        this.fromType = fromType;
+        this.to = to;
+        this.toType = toType;
+        this.from.addOutgoingConnection(fromType, this);
+        this.to.addIncomingConnection(toType, this);
+    }
+
+    public synchronized void terminate() {
+        this.from.removeOutgoingConnection(fromType, this);
+        this.to.removeIncomingConnection(toType, this);
+        this.from = null;
+        this.fromType = null;
+        this.to = null;
+        this.toType = null;
+    }
+
+    public Node getFrom() {
+        return this.from;
+    }
+
+    public Node getTo() {
+        return this.to;
+    }
+
+    public String getFromType() {
+        return this.fromType;
+    }
+
+    public String getToType() {
+        return this.toType;
+    }
+
+    public String toString() {
+        final StringBuffer sb = new StringBuffer("Connection ");
+        sb.append(getFrom());
+        sb.append(" [type=");
+        sb.append(getFromType());
+        sb.append("]");
+        sb.append(" - ");
+        sb.append(getTo());
+        sb.append(" [type=");
+        sb.append(getToType());
+        sb.append("]");
+        return sb.toString();
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/ConstraintImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/ConstraintImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/ConstraintImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,82 @@
+package org.drools.workflow.core.impl;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.drools.workflow.core.Constraint;
+
+/**
+ * Default implementation of a constraint.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class ConstraintImpl implements Constraint, Serializable {
+
+    private static final long  serialVersionUID = 400L;
+
+    private String             name;
+    private String             constraint;
+    private int                priority;
+    private String             dialect;
+    private String             type;
+
+    public String getConstraint() {
+        return this.constraint;
+    }
+
+    public void setConstraint(final String constraint) {
+        this.constraint = constraint;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    public String toString() {
+        return this.name;
+    }
+
+    public int getPriority() {
+        return this.priority;
+    }
+
+    public void setPriority(final int priority) {
+        this.priority = priority;
+    }
+
+    public String getDialect() {
+        return dialect;
+    }
+
+    public void setDialect(String dialect) {
+        this.dialect = dialect;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/DroolsConsequenceAction.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/DroolsConsequenceAction.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/DroolsConsequenceAction.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,36 @@
+package org.drools.workflow.core.impl;
+
+import java.io.Serializable;
+
+public class DroolsConsequenceAction implements Serializable {
+	
+    private static final long serialVersionUID = 400L;
+    
+    private String dialect = "mvel";
+    private String consequence;
+	
+	public DroolsConsequenceAction(String dialect, String consequence) {
+	    this.dialect = dialect;
+		this.consequence = consequence;
+	}
+	
+	public void setConsequence(String consequence) {
+		this.consequence = consequence;
+	}
+	
+	public String getConsequence() {
+		return consequence;
+	}
+	
+	public void setDialect(String dialect) {
+	    this.dialect = dialect;
+	}
+	
+	public String getDialect() {
+	    return dialect;
+	}
+
+	public String toString() {
+		return consequence;
+	}
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/NodeContainerImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/NodeContainerImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/NodeContainerImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,67 @@
+package org.drools.workflow.core.impl;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.NodeContainer;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class NodeContainerImpl implements Serializable, NodeContainer {
+
+    private static final long serialVersionUID = 400L;
+
+    private Map<Long, Node> nodes;
+
+    private long lastNodeId;
+
+    public NodeContainerImpl() {
+        this.nodes = new HashMap<Long, Node>();
+    }
+
+    public void addNode(final Node node) {
+        validateAddNode(node);
+        if (!this.nodes.containsValue(node)) {
+            node.setId(++this.lastNodeId);
+            this.nodes.put(new Long(node.getId()), node);
+        }
+    }
+
+    protected void validateAddNode(Node node) {
+        if (node == null) {
+            throw new IllegalArgumentException("Node is null!");
+        }
+    }
+
+    public Node[] getNodes() {
+        return (Node[]) this.nodes.values()
+                .toArray(new Node[this.nodes.size()]);
+    }
+
+    public Node getNode(final long id) {
+        final Long idLong = new Long(id);
+        if (!this.nodes.containsKey(idLong)) {
+            throw new IllegalArgumentException("Unknown node id: " + id);
+        }
+        return (Node) this.nodes.get(idLong);
+    }
+
+    public void removeNode(final Node node) {
+        validateRemoveNode(node);
+        this.nodes.remove(new Long(node.getId()));
+    }
+
+    protected void validateRemoveNode(Node node) {
+        if (node == null) {
+            throw new IllegalArgumentException("Node is null");
+        }
+        if (this.nodes.get(node.getId()) == null) {
+            throw new IllegalArgumentException("Unknown node: " + node);
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/NodeImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/NodeImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/NodeImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,176 @@
+package org.drools.workflow.core.impl;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.workflow.core.Connection;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.NodeContainer;
+
+/**
+ * Default implementation of a node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public abstract class NodeImpl implements Node, Serializable {
+
+    protected static final NodeImpl[] EMPTY_NODE_ARRAY = new NodeImpl[0];
+
+    private long id;
+
+    private String name;
+    private Map<String, List<Connection>> incomingConnections;
+    private Map<String, List<Connection>> outgoingConnections;
+    private NodeContainer nodeContainer;
+
+    public NodeImpl() {
+        this.id = -1;
+        this.incomingConnections = new HashMap<String, List<Connection>>();
+        this.outgoingConnections = new HashMap<String, List<Connection>>();
+    }
+
+    public long getId() {
+        return this.id;
+    }
+
+    public void setId(final long id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    public Map<String, List<Connection>> getIncomingConnections() {
+        // TODO: users can still modify the lists inside this Map
+        return Collections.unmodifiableMap(this.incomingConnections);
+    }
+
+    public Map<String, List<Connection>> getOutgoingConnections() {
+        // TODO: users can still modify the lists inside this Map
+        return Collections.unmodifiableMap(this.outgoingConnections);
+    }
+
+    public void addIncomingConnection(final String type, final Connection connection) {
+        validateAddIncomingConnection(type, connection);
+        List<Connection> connections = this.incomingConnections.get(type);
+        if (connections == null) {
+            connections = new ArrayList<Connection>();
+            this.incomingConnections.put(type, connections);
+        }
+        connections.add(connection);
+    }
+
+    public void validateAddIncomingConnection(final String type, final Connection connection) {
+        if (type == null) {
+            throw new IllegalArgumentException("Connection type cannot be null");
+        }
+        if (connection == null) {
+            throw new IllegalArgumentException("Connection cannot be null");
+        }
+    }
+    
+    public List<Connection> getIncomingConnections(String type) {
+        List<Connection> result = incomingConnections.get(type);
+        if (result == null) {
+            return new ArrayList<Connection>();
+        }
+        return result;
+    }
+
+    public void addOutgoingConnection(final String type, final Connection connection) {
+        validateAddOutgoingConnection(type, connection);
+        List<Connection> connections = this.outgoingConnections.get(type);
+        if (connections == null) {
+            connections = new ArrayList<Connection>();
+            this.outgoingConnections.put(type, connections);
+        }
+        connections.add(connection);
+    }
+
+    public void validateAddOutgoingConnection(final String type, final Connection connection) {
+        if (type == null) {
+            throw new IllegalArgumentException("Connection type cannot be null");
+        }
+        if (connection == null) {
+            throw new IllegalArgumentException("Connection cannot be null");
+        }
+    }
+
+    public List<Connection> getOutgoingConnections(String type) {
+        List<Connection> result = outgoingConnections.get(type);
+        if (result == null) {
+            return new ArrayList<Connection>();
+        }
+        return result;
+    }
+
+    public void removeIncomingConnection(final String type, final Connection connection) {
+        validateRemoveIncomingConnection(type, connection);
+        this.incomingConnections.get(type).remove(connection);
+    }
+
+    public void validateRemoveIncomingConnection(final String type, final Connection connection) {
+        if (type == null) {
+            throw new IllegalArgumentException("Connection type cannot be null");
+        }
+        if (connection == null) {
+            throw new IllegalArgumentException("Connection is null");
+        }
+        if (!incomingConnections.get(type).contains(connection)) {
+            throw new IllegalArgumentException("Given connection <"
+                    + connection + "> is not part of the incoming connections");
+        }
+    }
+
+    public void removeOutgoingConnection(final String type, final Connection connection) {
+        validateRemoveOutgoingConnection(type, connection);
+        this.outgoingConnections.get(type).remove(connection);
+    }
+
+    public void validateRemoveOutgoingConnection(final String type, final Connection connection) {
+        if (type == null) {
+            throw new IllegalArgumentException("Connection type cannot be null");
+        }
+        if (connection == null) {
+            throw new IllegalArgumentException("Connection is null");
+        }
+        if (!this.outgoingConnections.get(type).contains(connection)) {
+            throw new IllegalArgumentException("Given connection <"
+                    + connection + "> is not part of the outgoing connections");
+        }
+    }
+    
+    public NodeContainer getNodeContainer() {
+        return nodeContainer;
+    }
+    
+    public void setNodeContainer(NodeContainer nodeContainer) {
+        this.nodeContainer = nodeContainer;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/WorkflowProcessImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/WorkflowProcessImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/impl/WorkflowProcessImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,94 @@
+package org.drools.workflow.core.impl;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.process.core.impl.ProcessImpl;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.NodeContainer;
+import org.drools.workflow.core.WorkflowProcess;
+
+/**
+ * Default implementation of a RuleFlow process.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class WorkflowProcessImpl extends ProcessImpl implements WorkflowProcess {
+
+    private static final long   serialVersionUID = 400L;
+
+    private NodeContainer nodeContainer;
+    private List<String> imports;
+    private Map<String, String> globals;
+    
+    public WorkflowProcessImpl() {
+        nodeContainer = createNodeContainer();
+    }
+    
+    protected NodeContainer createNodeContainer() {
+        return new NodeContainerImpl();
+    }
+    
+    public Node[] getNodes() {
+        return nodeContainer.getNodes();
+    }
+
+    public Node getNode(final long id) {
+        return nodeContainer.getNode(id);
+    }
+
+    public void removeNode(final Node node) {
+        nodeContainer.removeNode(node);
+        node.setNodeContainer(null);
+    }
+
+    public void addNode(final Node node) {
+        nodeContainer.addNode(node);
+        node.setNodeContainer(this);
+    }
+
+    public List<String> getImports() {
+        return imports;
+    }
+
+    public void setImports(List<String> imports) {
+        this.imports = imports;
+    }
+    
+    public Map<String, String> getGlobals() {
+        return globals;
+    }
+
+    public void setGlobals(Map<String, String> globals) {
+        this.globals = globals;
+    }
+
+    public String[] getGlobalNames() {
+        final List<String> result = new ArrayList<String>();
+        if (this.globals != null) {
+            for ( Iterator<String> iterator = this.globals.keySet().iterator(); iterator.hasNext(); ) {
+                result.add(iterator.next());
+            }
+        }
+        return result.toArray(new String[result.size()]);
+    }
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/ActionNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/ActionNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/ActionNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,39 @@
+package org.drools.workflow.core.node;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/**
+ * Default implementation of an action node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class ActionNode extends SequenceNode {
+
+	private static final long serialVersionUID = 400L;
+	
+	private Object action;
+
+	public Object getAction() {
+		return action;
+	}
+
+	public void setAction(Object action) {
+		this.action = action;
+	}
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/CompositeNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/CompositeNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/CompositeNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,230 @@
+package org.drools.workflow.core.node;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.workflow.core.Connection;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.NodeContainer;
+import org.drools.workflow.core.impl.ConnectionImpl;
+import org.drools.workflow.core.impl.NodeContainerImpl;
+import org.drools.workflow.core.impl.NodeImpl;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class CompositeNode extends NodeImpl implements NodeContainer {
+
+    private static final long serialVersionUID = 400L;
+    
+    private NodeContainer nodeContainer;
+    private Map<String, CompositeNode.NodeAndType> inConnectionMap = new HashMap<String, CompositeNode.NodeAndType>();
+    private Map<String, CompositeNode.NodeAndType> outConnectionMap = new HashMap<String, CompositeNode.NodeAndType>();
+    
+    public CompositeNode() {
+        this.nodeContainer = new NodeContainerImpl();
+    }
+    
+    public Node getNode(long id) {
+        return nodeContainer.getNode(id);
+    }
+
+    public Node[] getNodes() {
+        return nodeContainer.getNodes();
+    }
+
+    public void addNode(Node node) {
+        nodeContainer.addNode(node);
+        node.setNodeContainer(this);
+    }
+
+    public void removeNode(Node node) {
+        nodeContainer.removeNode(node);
+        node.setNodeContainer(null);
+    }
+    
+    public void linkIncomingConnections(String inType, CompositeNode.NodeAndType inNode) {
+        inConnectionMap.put(inType, inNode);
+    }
+    
+    public void linkOutgoingConnections(CompositeNode.NodeAndType outNode, String outType) {
+        outConnectionMap.put(outType, outNode);
+    }
+
+    public CompositeNode.NodeAndType getLinkedIncomingNode(String inType) {
+        return inConnectionMap.get(inType);
+    }
+
+    public CompositeNode.NodeAndType getLinkedOutgoingNode(String outType) {
+        return outConnectionMap.get(outType);
+    }
+    
+    public void validateAddIncomingConnection(final String type, final Connection connection) {
+        CompositeNode.NodeAndType nodeAndType = getLinkedIncomingNode(type);
+        if (nodeAndType == null) {
+            throw new IllegalArgumentException(
+                "Cannot add incoming connections to a composite node until these connections can be mapped correctly to a subnode!");
+        }
+        ((NodeImpl) nodeAndType.getNode()).validateAddIncomingConnection(nodeAndType.getType(), connection);
+    }
+    
+    public void addIncomingConnection(String type, Connection connection) {
+        super.addIncomingConnection(type, connection);
+        CompositeNodeStart start = new CompositeNodeStart(connection.getFrom(), type);
+        addNode(start);
+        CompositeNode.NodeAndType inNode = getLinkedIncomingNode(type);
+        new ConnectionImpl(
+            start, Node.CONNECTION_DEFAULT_TYPE, 
+            inNode.getNode(), inNode.getType());
+    }
+    
+    public void validateAddOutgoingConnection(final String type, final Connection connection) {
+        CompositeNode.NodeAndType nodeAndType = getLinkedOutgoingNode(type);
+        if (nodeAndType == null) {
+            throw new IllegalArgumentException(
+                "Cannot add outgoing connections to a composite node until these connections can be mapped correctly to a subnode!");
+        }
+        ((NodeImpl) nodeAndType.getNode()).validateAddOutgoingConnection(nodeAndType.getType(), connection);
+    }
+    
+    public void addOutgoingConnection(String type, Connection connection) {
+        super.addOutgoingConnection(type, connection);
+        CompositeNodeEnd end = new CompositeNodeEnd(connection.getTo(), type);
+        addNode(end);
+        CompositeNode.NodeAndType outNode = getLinkedOutgoingNode(type);
+        new ConnectionImpl(
+            outNode.getNode(), outNode.getType(), 
+            end, Node.CONNECTION_DEFAULT_TYPE);
+    }
+    
+    public void validateRemoveIncomingConnection(final String type, final Connection connection) {
+        CompositeNode.NodeAndType nodeAndType = getLinkedIncomingNode(type);
+        ((NodeImpl) nodeAndType.getNode()).validateRemoveIncomingConnection(nodeAndType.getType(), connection);
+    }
+    
+    public void removeIncomingConnection(String type, Connection connection) {
+        super.removeIncomingConnection(type, connection);
+        CompositeNode.NodeAndType inNode = getLinkedIncomingNode(type);
+        List<Connection> connections = inNode.getNode().getIncomingConnections(inNode.getType());
+        for (Iterator<Connection> iterator = connections.iterator(); iterator.hasNext(); ) {
+            Connection internalConnection = iterator.next();
+            if (((CompositeNodeStart) internalConnection.getFrom()).getInNode().equals(connection.getFrom())) {
+                ((ConnectionImpl) internalConnection).terminate();
+                removeNode(internalConnection.getFrom());
+            }
+        }
+    }
+    
+    public void validateRemoveOutgoingConnection(final String type, final Connection connection) {
+        CompositeNode.NodeAndType nodeAndType = getLinkedOutgoingNode(type);
+        ((NodeImpl) nodeAndType.getNode()).validateRemoveOutgoingConnection(nodeAndType.getType(), connection);
+    }
+    
+    public void removeOutgoingConnection(String type, Connection connection) {
+        super.removeOutgoingConnection(type, connection);
+        CompositeNode.NodeAndType outNode = getLinkedOutgoingNode(type);
+        List<Connection> connections = outNode.getNode().getOutgoingConnections(outNode.getType());
+        for (Iterator<Connection> iterator = connections.iterator(); iterator.hasNext(); ) {
+            Connection internalConnection = iterator.next();
+            if (((CompositeNodeEnd) internalConnection.getTo()).getOutNode().equals(connection.getTo())) {
+                ((ConnectionImpl) internalConnection).terminate();
+                removeNode(internalConnection.getTo());
+            }
+        }
+    }
+    
+    public static class NodeAndType {
+
+        private Node node;
+        private String type;
+        
+        public NodeAndType(Node node, String type) {
+            if (node == null || type == null) {
+                throw new IllegalArgumentException(
+                    "Node or type may not be null!");
+            }
+            this.node = node;
+            this.type = type;
+        }
+        
+        public Node getNode() {
+            return node;
+        }
+
+        public String getType() {
+            return type;
+        }
+        
+        public boolean equals(Object o) {
+            if (o instanceof NodeAndType) {
+                return node.equals(((NodeAndType) o).node)
+                    && type.equals(((NodeAndType) o).type); 
+            }
+            return false;
+        }
+        
+        public int hashCode() {
+            return node.hashCode() + 13*type.hashCode();
+        }
+        
+    }
+    
+    public class CompositeNodeStart extends NodeImpl {
+
+        private static final long serialVersionUID = 400L;
+        
+        private Node outNode;
+        private String outType;
+        
+        public CompositeNodeStart(Node outNode, String outType) {
+            setName("Composite node start");
+            this.outNode = outNode;
+            this.outType = outType;
+        }
+        
+        public Node getInNode() {
+            return outNode;
+        }
+        
+        public String getInType() {
+            return outType;
+        }
+        
+        public Connection getTo() {
+            final List<Connection> list =
+                getOutgoingConnections(Node.CONNECTION_DEFAULT_TYPE);
+            if (list.size() > 0) {
+                return (Connection) list.get(0);
+            }
+            return null;
+        }
+        
+    }
+    
+    public class CompositeNodeEnd extends NodeImpl {
+
+        private static final long serialVersionUID = 400L;
+        
+        private Node outNode;
+        private String outType;
+        
+        public CompositeNodeEnd(Node outNode, String outType) {
+            setName("Composite node end");
+            this.outNode = outNode;
+            this.outType = outType;
+        }
+        
+        public Node getOutNode() {
+            return outNode;
+        }
+        
+        public String getOutType() {
+            return outType;
+        }
+        
+    }
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/EndNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/EndNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/EndNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,39 @@
+package org.drools.workflow.core.node;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.workflow.core.Connection;
+
+/**
+ * Default implementation of an end node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class EndNode extends SequenceNode {
+
+    private static final long serialVersionUID = 400L;
+
+    public void validateAddOutgoingConnection(final String type, final Connection connection) {
+        throw new UnsupportedOperationException(
+            "An end node does not have an outgoing connection!");
+    }
+
+    public void validateRemoveOutgoingConnection(final String type, final Connection connection) {
+        throw new UnsupportedOperationException(
+            "An end node does not have an outgoing connection!");
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/Join.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/Join.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/Join.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,101 @@
+package org.drools.workflow.core.node;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.List;
+
+import org.drools.workflow.core.Connection;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.impl.NodeImpl;
+
+/**
+ * Default implementation of a join.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class Join extends NodeImpl {
+
+    public static final int TYPE_UNDEFINED     = 0;
+    /**
+     * The outgoing connection of a join of this type is triggered
+     * when all its incoming connections have been triggered.
+     */
+    public static final int TYPE_AND           = 1;
+    /**
+     * The outgoing connection of a join of this type is triggered
+     * when one of its incoming connections has been triggered.
+     */
+    public static final int TYPE_XOR           = 2;
+    /**
+     * The outgoing connection of a join of this type is triggered
+     * when one of its incoming connections has been triggered. It then
+     * waits until all other incoming connections have been triggered
+     * before allowing 
+     */
+    public static final int TYPE_DISCRIMINATOR = 3;
+    
+    private static final long serialVersionUID = 400L;
+
+    private int               type;
+
+    public Join() {
+        this.type = TYPE_UNDEFINED;
+    }
+
+    public void setType(final int type) {
+        this.type = type;
+    }
+
+    public int getType() {
+        return this.type;
+    }
+
+    public Connection getTo() {
+        final List<Connection> list =
+            getOutgoingConnections(Node.CONNECTION_DEFAULT_TYPE);
+        if (list.size() > 0) {
+            return (Connection) list.get(0);
+        }
+        return null;
+    }
+    
+    public List<Connection> getDefaultIncomingConnections() {
+        return getIncomingConnections(Node.CONNECTION_DEFAULT_TYPE);
+    }
+
+    public void validateAddIncomingConnection(final String type,
+            final Connection connection) {
+        super.validateAddIncomingConnection(type, connection);
+        if (!Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
+            throw new IllegalArgumentException(
+                "This type of node only accepts default incoming connection type!");
+        }
+    }
+
+    public void validateAddOutgoingConnection(final String type, final Connection connection) {
+        super.validateAddOutgoingConnection(type, connection);
+        if (!Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
+            throw new IllegalArgumentException(
+                "This type of node only accepts default outgoing connection type!");
+        }
+        if (!getOutgoingConnections(Node.CONNECTION_DEFAULT_TYPE).isEmpty()) {
+            throw new IllegalArgumentException(
+                "This type of node cannot have more than one outgoing connection");
+        }
+    }
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/MilestoneNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/MilestoneNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/MilestoneNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,39 @@
+package org.drools.workflow.core.node;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/**
+ * Default implementation of a milestone node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class MilestoneNode extends SequenceNode {
+
+	private static final long serialVersionUID = 8552568488755348247L;
+
+	private String            constraint;
+
+    public void setConstraint(final String constraint) {
+        this.constraint = constraint;
+    }
+
+    public String getConstraint() {
+        return this.constraint;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/RuleSetNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/RuleSetNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/RuleSetNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,39 @@
+package org.drools.workflow.core.node;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/**
+ * Default implementation of a RuleSet node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class RuleSetNode extends SequenceNode {
+
+    private static final long serialVersionUID = 400L;
+
+    private String ruleFlowGroup;
+
+    public void setRuleFlowGroup(final String ruleFlowGroup) {
+        this.ruleFlowGroup = ruleFlowGroup;
+    }
+
+    public String getRuleFlowGroup() {
+        return this.ruleFlowGroup;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/SequenceNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/SequenceNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/SequenceNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,59 @@
+package org.drools.workflow.core.node;
+
+import java.util.List;
+
+import org.drools.workflow.core.Connection;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.impl.NodeImpl;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public abstract class SequenceNode extends NodeImpl {
+
+    public Connection getFrom() {
+        final List<Connection> list =
+            getIncomingConnections(Node.CONNECTION_DEFAULT_TYPE);
+        if (list.size() > 0) {
+            return (Connection) list.get(0);
+        }
+        return null;
+    }
+
+    public Connection getTo() {
+        final List<Connection> list =
+            getOutgoingConnections(Node.CONNECTION_DEFAULT_TYPE);
+        if (list.size() > 0) {
+            return (Connection) list.get(0);
+        }
+        return null;
+    }
+
+    public void validateAddIncomingConnection(final String type,
+            final Connection connection) {
+        super.validateAddIncomingConnection(type, connection);
+        if (!Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
+            throw new IllegalArgumentException(
+                "This type of node only accepts default incoming connection type!");
+        }
+        if (getIncomingConnections(Node.CONNECTION_DEFAULT_TYPE) != null
+                && !getIncomingConnections(Node.CONNECTION_DEFAULT_TYPE).isEmpty()) {
+            throw new IllegalArgumentException(
+                "This type of node cannot have more than one incoming connection!");
+        }
+    }
+
+    public void validateAddOutgoingConnection(final String type, final Connection connection) {
+        super.validateAddOutgoingConnection(type, connection);
+        if (!Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
+            throw new IllegalArgumentException(
+                "This type of node only accepts default outgoing connection type!");
+        }
+        if (getOutgoingConnections(Node.CONNECTION_DEFAULT_TYPE) != null
+                && !getOutgoingConnections(Node.CONNECTION_DEFAULT_TYPE).isEmpty()) {
+            throw new IllegalArgumentException(
+                "This type of node cannot have more than one outgoing connection!");
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/Split.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/Split.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/Split.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,168 @@
+package org.drools.workflow.core.node;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.drools.workflow.core.Connection;
+import org.drools.workflow.core.Constraint;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.impl.NodeImpl;
+
+/**
+ * Default implementation of a split node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class Split extends NodeImpl {
+
+    public static final int TYPE_UNDEFINED = 0;
+    /**
+     * All outgoing connections of a split of this type are triggered
+     * when its incoming connection has been triggered.  A split of this
+     * type should have no constraints linked to any of its outgoing
+     * connections.
+     */
+    public static final int TYPE_AND       = 1;
+    /**
+     * Exactly one outgoing connection of a split of this type is triggered
+     * when its incoming connection has been triggered.  Which connection
+     * is based on the constraints associated with each of the connections:
+     * the connection with the highest priority whose constraint is satisfied
+     * is triggered.  
+     */
+    public static final int TYPE_XOR       = 2;
+    /**
+     * One or multiple outgoing connections of a split of this type are
+     * triggered when its incoming connection has been triggered.  Which
+     * connections is based on the constraints associated with each of the
+     * connections: all connections whose constraint is satisfied are
+     * triggered.  
+     */
+    public static final int TYPE_OR        = 3;
+
+    private static final long serialVersionUID = 400L;
+
+    private int type;
+    private Map<Connection, Constraint> constraints = new HashMap<Connection, Constraint>();
+
+    public Split() {
+        this.type = TYPE_UNDEFINED;
+    }
+
+    public Split(final int type) {
+        this.type = type;
+    }
+
+    public void setType(final int type) {
+        this.type = type;
+    }
+
+    public int getType() {
+        return this.type;
+    }
+
+    public Constraint getConstraint(final Connection connection) {
+        if ( connection == null ) {
+            throw new IllegalArgumentException( "connection is null" );
+        }
+
+        // dirty hack because keys were entered wrong
+        // probably caused by xstreams
+        // TODO xstream 1.3.0 should fix this by default; in 1.2.2 it's fixable: http://jira.codehaus.org/browse/XSTR-363
+        final HashMap<Connection, Constraint> newMap = new HashMap<Connection, Constraint>();
+        for (final Iterator<Map.Entry<Connection, Constraint>> it = this.constraints.entrySet().iterator(); it.hasNext(); ) {
+            final Entry<Connection, Constraint> entry = it.next();
+            newMap.put(entry.getKey(), entry.getValue());
+        }
+        this.constraints = newMap;
+
+        if ( this.type == TYPE_OR || this.type == TYPE_XOR ) {
+            return this.constraints.get(connection);
+        }
+        throw new UnsupportedOperationException( "Constraints are " + "only supported with XOR or OR split types, not with: " + getType() );
+    }
+
+    public void setConstraint(final Connection connection,
+                              final Constraint constraint) {
+        if ( this.type == TYPE_OR || this.type == TYPE_XOR ) {
+            if ( connection == null ) {
+                throw new IllegalArgumentException( "connection is null" );
+            }
+            if (getOutgoingConnections(Node.CONNECTION_DEFAULT_TYPE) != null
+                    && !getOutgoingConnections(Node.CONNECTION_DEFAULT_TYPE).contains(connection)) {
+                throw new IllegalArgumentException("connection is unknown:" + connection);
+            }
+            this.constraints.put( connection,
+                                  constraint );
+        } else {
+            throw new UnsupportedOperationException( "Constraints are " + "only supported with XOR or OR split types, not with type:" + getType() );
+        }
+    }
+
+    public Map<Connection, Constraint> getConstraints() {
+        if ( this.type == TYPE_OR || this.type == TYPE_XOR ) {
+            return Collections.unmodifiableMap( this.constraints );
+        }
+        throw new UnsupportedOperationException( "Constraints are " + "only supported with XOR or OR split types, not with: " + getType() );
+    }
+
+    public Connection getFrom() {
+        final List<Connection> list =
+            getIncomingConnections(Node.CONNECTION_DEFAULT_TYPE);
+        if (list.size() > 0) {
+            return (Connection) list.get(0);
+        }
+        return null;
+    }
+    
+    public List<Connection> getDefaultOutgoingConnections() {
+        return getOutgoingConnections(Node.CONNECTION_DEFAULT_TYPE);
+    }
+
+    public void validateAddIncomingConnection(final String type,
+            final Connection connection) {
+        super.validateAddIncomingConnection(type, connection);
+        if (!Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
+            throw new IllegalArgumentException(
+                "This type of node only accepts default incoming connection type!");
+        }
+        if (!getIncomingConnections(Node.CONNECTION_DEFAULT_TYPE).isEmpty()) {
+            throw new IllegalArgumentException(
+                "This type of node cannot have more than one incoming connection!");
+        }
+    }
+
+    public void validateAddOutgoingConnection(final String type, final Connection connection) {
+        super.validateAddOutgoingConnection(type, connection);
+        if (!Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
+            throw new IllegalArgumentException(
+                "This type of node only accepts default outgoing connection type!");
+        }
+    }
+
+    public void removeOutgoingConnection(final String type, final Connection connection) {
+        super.removeOutgoingConnection(type, connection);
+        this.constraints.remove(connection);
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/StartNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/StartNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/StartNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,40 @@
+package org.drools.workflow.core.node;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.workflow.core.Connection;
+
+/**
+ * Default implementation of a start node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class StartNode extends SequenceNode {
+
+    private static final long serialVersionUID = 400L;
+
+    public void validateAddIncomingConnection(final String type, final Connection connection) {
+        throw new UnsupportedOperationException(
+            "A start node does not have an incoming connection!");
+    }
+
+    public void validateRemoveIncomingConnection(final String type, final Connection connection) {
+        throw new UnsupportedOperationException(
+            "A start node does not have an incoming connection!");
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/SubProcessNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/SubProcessNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/SubProcessNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,48 @@
+package org.drools.workflow.core.node;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/**
+ * Default implementation of a sub-flow node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class SubProcessNode extends SequenceNode {
+
+	private static final long serialVersionUID = 400L;
+	
+	private String            processId;
+	private boolean           waitForCompletion = true;
+
+    public void setProcessId(final String processId) {
+        this.processId = processId;
+    }
+
+    public String getProcessId() {
+        return this.processId;
+    }
+
+    public boolean isWaitForCompletion() {
+        return waitForCompletion;
+    }
+
+    public void setWaitForCompletion(boolean waitForCompletion) {
+        this.waitForCompletion = waitForCompletion;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/WorkItemNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/WorkItemNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/core/node/WorkItemNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,70 @@
+package org.drools.workflow.core.node;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.process.core.Work;
+
+/**
+ * Default implementation of a task node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class WorkItemNode extends SequenceNode {
+
+	private static final long serialVersionUID = 400L;
+	
+	private Work work;
+    private Map<String, String> inMapping = new HashMap<String, String>();
+    private Map<String, String> outMapping = new HashMap<String, String>();
+
+	public Work getWork() {
+		return work;
+	}
+
+	public void setWork(Work task) {
+		this.work = task;
+	}
+	
+    public void addInMapping(String parameterName, String variableName) {
+        inMapping.put(parameterName, variableName);
+    }
+    
+    public String getInMapping(String parameterName) {
+        return inMapping.get(parameterName);
+    }
+
+    public Map<String, String> getInMappings() {
+        return Collections.unmodifiableMap(inMapping);
+    }
+    
+    public void addOutMapping(String parameterName, String variableName) {
+        outMapping.put(parameterName, variableName);
+    }
+    
+    public String getOutMapping(String parameterName) {
+        return outMapping.get(parameterName);
+    }
+
+    public Map<String, String> getOutMappings() {
+        return Collections.unmodifiableMap(outMapping);
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/NodeInstance.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/NodeInstance.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/NodeInstance.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,46 @@
+package org.drools.workflow.instance;
+
+import org.drools.workflow.core.Node;
+
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Represents a node instance in a RuleFlow. This is the runtime counterpart
+ * of a node, containing all runtime state.  Node instance classes also
+ * contain the logic on what to do when it is being triggered (start
+ * executing) or completed (end of execution).
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface NodeInstance {
+
+    long getId();
+
+    long getNodeId();
+
+    WorkflowProcessInstance getProcessInstance();
+
+    NodeInstanceContainer getNodeInstanceContainer();
+    
+    void trigger(NodeInstance from, String type);
+
+    void cancel();
+    
+    Node getNode();
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/NodeInstanceContainer.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/NodeInstanceContainer.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/NodeInstanceContainer.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,28 @@
+package org.drools.workflow.instance;
+
+import java.util.Collection;
+
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.NodeContainer;
+
+/**
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface NodeInstanceContainer {
+
+    Collection<NodeInstance> getNodeInstances();
+
+    Collection<NodeInstance> getNodeInstances(boolean recursive);
+
+    NodeInstance getFirstNodeInstance(long nodeId);
+
+    NodeInstance getNodeInstance(Node node);
+
+    void addNodeInstance(NodeInstance nodeInstance);
+
+    void removeNodeInstance(NodeInstance nodeInstance);
+    
+    NodeContainer getNodeContainer();
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/WorkflowProcessInstance.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/WorkflowProcessInstance.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/WorkflowProcessInstance.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,44 @@
+package org.drools.workflow.instance;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.Agenda;
+import org.drools.WorkingMemory;
+import org.drools.process.instance.ProcessInstance;
+import org.drools.process.instance.WorkItemListener;
+import org.drools.workflow.core.WorkflowProcess;
+
+/**
+ * A process instance for a RuleFlow process.
+ * Contains a reference to all its node instances, and the agenda that
+ * is controlling the RuleFlow process.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface WorkflowProcessInstance extends ProcessInstance, NodeInstanceContainer {
+
+    WorkflowProcess getWorkflowProcess();
+
+    WorkingMemory getWorkingMemory();
+
+    Agenda getAgenda();
+    
+    void addWorkItemListener(WorkItemListener listener);
+
+    void removeWorkItemListener(WorkItemListener listener);
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/ConstraintEvaluator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/ConstraintEvaluator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/ConstraintEvaluator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,13 @@
+package org.drools.workflow.instance.impl;
+
+import org.drools.workflow.core.Connection;
+import org.drools.workflow.core.Constraint;
+import org.drools.workflow.instance.node.SplitInstance;
+
+public interface ConstraintEvaluator extends Constraint {
+    
+    // TODO: make this work for more than only splits
+    public boolean evaluate(SplitInstance instance,
+                            Connection connection,
+                            Constraint constraint);
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/NodeInstanceFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/NodeInstanceFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/NodeInstanceFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,12 @@
+package org.drools.workflow.instance.impl;
+
+import org.drools.workflow.core.Node;
+import org.drools.workflow.instance.NodeInstance;
+import org.drools.workflow.instance.NodeInstanceContainer;
+import org.drools.workflow.instance.WorkflowProcessInstance;
+
+public interface NodeInstanceFactory {
+    
+	NodeInstance getNodeInstance(Node node, WorkflowProcessInstance processInstance, NodeInstanceContainer nodeInstanceContainer);
+	
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/NodeInstanceFactoryRegistry.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/NodeInstanceFactoryRegistry.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/NodeInstanceFactoryRegistry.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,66 @@
+package org.drools.workflow.instance.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.node.ActionNode;
+import org.drools.workflow.core.node.EndNode;
+import org.drools.workflow.core.node.Join;
+import org.drools.workflow.core.node.MilestoneNode;
+import org.drools.workflow.core.node.RuleSetNode;
+import org.drools.workflow.core.node.Split;
+import org.drools.workflow.core.node.StartNode;
+import org.drools.workflow.core.node.SubProcessNode;
+import org.drools.workflow.core.node.WorkItemNode;
+import org.drools.workflow.instance.impl.factory.CreateNewNodeFactory;
+import org.drools.workflow.instance.impl.factory.ReuseNodeFactory;
+import org.drools.workflow.instance.node.ActionNodeInstance;
+import org.drools.workflow.instance.node.EndNodeInstance;
+import org.drools.workflow.instance.node.JoinInstance;
+import org.drools.workflow.instance.node.MilestoneNodeInstance;
+import org.drools.workflow.instance.node.RuleSetNodeInstance;
+import org.drools.workflow.instance.node.SplitInstance;
+import org.drools.workflow.instance.node.StartNodeInstance;
+import org.drools.workflow.instance.node.SubProcessNodeInstance;
+import org.drools.workflow.instance.node.WorkItemNodeInstance;
+
+public class NodeInstanceFactoryRegistry {
+    public static final NodeInstanceFactoryRegistry          instance = new NodeInstanceFactoryRegistry();
+
+    private Map<Class< ? extends Node>, NodeInstanceFactory> registry;
+
+    public NodeInstanceFactoryRegistry() {
+        this.registry = new HashMap<Class< ? extends Node>, NodeInstanceFactory>();
+
+        // hard wired nodes:
+        register( RuleSetNode.class,
+                  new CreateNewNodeFactory( RuleSetNodeInstance.class ) );
+        register( Split.class,
+                  new CreateNewNodeFactory( SplitInstance.class ) );
+        register( Join.class,
+                  new ReuseNodeFactory( JoinInstance.class ) );
+        register( StartNode.class,
+                  new CreateNewNodeFactory( StartNodeInstance.class ) );
+        register( EndNode.class,
+                  new CreateNewNodeFactory( EndNodeInstance.class ) );
+        register( MilestoneNode.class,
+                  new CreateNewNodeFactory( MilestoneNodeInstance.class ) );
+        register( SubProcessNode.class,
+                  new CreateNewNodeFactory( SubProcessNodeInstance.class ) );
+        register( ActionNode.class,
+                  new CreateNewNodeFactory( ActionNodeInstance.class ) );
+        register( WorkItemNode.class,
+                  new CreateNewNodeFactory( WorkItemNodeInstance.class ) );
+    }
+
+    public void register(Class< ? extends Node> cls,
+                         NodeInstanceFactory factory) {
+        this.registry.put( cls,
+                           factory );
+    }
+
+    public NodeInstanceFactory getProcessNodeInstanceFactory(Node node) {
+        return this.registry.get( node.getClass() );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/NodeInstanceImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/NodeInstanceImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/NodeInstanceImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,90 @@
+package org.drools.workflow.instance.impl;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.drools.common.EventSupport;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.instance.NodeInstance;
+import org.drools.workflow.instance.NodeInstanceContainer;
+import org.drools.workflow.instance.WorkflowProcessInstance;
+
+/**
+ * Default implementation of a RuleFlow node instance.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public abstract class NodeInstanceImpl implements NodeInstance, Serializable {
+
+    private long id;
+    private long nodeId;
+    private WorkflowProcessInstance processInstance;
+    private NodeInstanceContainer nodeInstanceContainer;
+
+    public void setId(final long id) {
+        this.id = id;
+    }
+
+    public long getId() {
+        return this.id;
+    }
+
+    public void setNodeId(final long nodeId) {
+        this.nodeId = nodeId;
+    }
+
+    public long getNodeId() {
+        return this.nodeId;
+    }
+
+    public void setProcessInstance(final WorkflowProcessInstance processInstance) {
+        this.processInstance = processInstance;
+    }
+
+    public WorkflowProcessInstance getProcessInstance() {
+        return this.processInstance;
+    }
+
+    public NodeInstanceContainer getNodeInstanceContainer() {
+        return this.nodeInstanceContainer;
+    }
+    
+    public void setNodeInstanceContainer(NodeInstanceContainer nodeInstanceContainer) {
+        this.nodeInstanceContainer = nodeInstanceContainer;
+        if (nodeInstanceContainer != null) {
+            nodeInstanceContainer.addNodeInstance(this);
+        }
+    }
+
+    public Node getNode() {
+        return this.nodeInstanceContainer.getNodeContainer().getNode( this.nodeId );
+    }
+    
+    public void cancel() {
+        nodeInstanceContainer.removeNodeInstance(this);
+    }
+    
+    public final void trigger(NodeInstance from, String type) {
+        ((EventSupport) getProcessInstance().getWorkingMemory()).getRuleFlowEventSupport().fireBeforeRuleFlowNodeTriggered(this, (InternalWorkingMemory) getProcessInstance().getWorkingMemory());
+        internalTrigger(from, type);
+        ((EventSupport) getProcessInstance().getWorkingMemory()).getRuleFlowEventSupport().fireAfterRuleFlowNodeTriggered(this, (InternalWorkingMemory) getProcessInstance().getWorkingMemory());
+    }
+    
+    public abstract void internalTrigger(NodeInstance from, String type);
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/ReturnValueConstraintEvaluator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/ReturnValueConstraintEvaluator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/ReturnValueConstraintEvaluator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,107 @@
+package org.drools.workflow.instance.impl;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.drools.spi.ReturnValueEvaluator;
+import org.drools.workflow.core.Connection;
+import org.drools.workflow.core.Constraint;
+import org.drools.workflow.instance.node.SplitInstance;
+
+/**
+ * Default implementation of a constraint.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class ReturnValueConstraintEvaluator
+    implements Constraint, ConstraintEvaluator, Serializable {
+
+    private static final long  serialVersionUID = 400L;
+
+    private String             name;
+    private String             constraint;
+    private int                priority;
+    private String             dialect;
+    private String             type;       
+    
+    private ReturnValueEvaluator evaluator;
+    
+    public String getConstraint() {
+        return this.constraint;
+    }
+
+    public void setConstraint(final String constraint) {
+        this.constraint = constraint;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    public String toString() {
+        return this.name;
+    }
+
+    public int getPriority() {
+        return this.priority;
+    }
+
+    public void setPriority(final int priority) {
+        this.priority = priority;
+    }
+
+    public String getDialect() {
+        return dialect;
+    }
+
+    public void setDialect(String dialect) {
+        this.dialect = dialect;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+    
+    public void setEvaluator(ReturnValueEvaluator evaluator) {
+        this.evaluator = evaluator;
+    }
+
+    public boolean evaluate(SplitInstance instance,
+                            Connection connection,
+                            Constraint constraint) {
+        Object value;
+        try {
+            value = this.evaluator.evaluate( instance.getProcessInstance().getWorkingMemory() );
+        } catch ( Exception e ) {
+            throw  new RuntimeException("unable to execute ReturnValueEvaluator", e);
+        }
+        if ( !(value instanceof Boolean) ) {
+            throw new RuntimeException("Constraints must return boolean values" );
+        }
+        return ((Boolean)value).booleanValue();
+    }    
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/RuleConstraintEvaluator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/RuleConstraintEvaluator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/RuleConstraintEvaluator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,106 @@
+package org.drools.workflow.instance.impl;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.Iterator;
+
+import org.drools.common.RuleFlowGroupNode;
+import org.drools.spi.Activation;
+import org.drools.spi.RuleFlowGroup;
+import org.drools.workflow.core.Connection;
+import org.drools.workflow.core.Constraint;
+import org.drools.workflow.instance.WorkflowProcessInstance;
+import org.drools.workflow.instance.node.SplitInstance;
+
+/**
+ * Default implementation of a constraint.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class RuleConstraintEvaluator implements Constraint,
+        ConstraintEvaluator, Serializable {
+
+    private static final long  serialVersionUID = 400L;
+
+    private String             name;
+    private String             constraint;
+    private int                priority;
+    private String             dialect;
+    private String             type;       
+    
+    public String getConstraint() {
+        return this.constraint;
+    }
+
+    public void setConstraint(final String constraint) {
+        this.constraint = constraint;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    public String toString() {
+        return this.name;
+    }
+
+    public int getPriority() {
+        return this.priority;
+    }
+
+    public void setPriority(final int priority) {
+        this.priority = priority;
+    }
+
+    public String getDialect() {
+        return dialect;
+    }
+
+    public void setDialect(String dialect) {
+        this.dialect = dialect;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+    
+    public boolean evaluate(SplitInstance instance,
+                            Connection connection,
+                            Constraint constraint) {
+        WorkflowProcessInstance processInstance = instance.getProcessInstance();
+        RuleFlowGroup systemRuleFlowGroup = processInstance.getAgenda().getRuleFlowGroup( "DROOLS_SYSTEM" );
+
+        String rule = "RuleFlow-Split-" + processInstance.getProcess().getId() + "-" + instance.getNode().getId() + "-" + connection.getTo().getId();
+        for ( Iterator activations = systemRuleFlowGroup.iterator(); activations.hasNext(); ) {
+            Activation activation = ((RuleFlowGroupNode) activations.next()).getActivation();
+            if ( rule.equals( activation.getRule().getName() ) ) {
+                return true;
+            }
+        }
+        return false;
+    }    
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/WorkflowProcessInstanceImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/WorkflowProcessInstanceImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/WorkflowProcessInstanceImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,183 @@
+package org.drools.workflow.instance.impl;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.drools.Agenda;
+import org.drools.WorkingMemory;
+import org.drools.common.EventSupport;
+import org.drools.common.InternalRuleBase;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.process.instance.WorkItem;
+import org.drools.process.instance.WorkItemListener;
+import org.drools.process.instance.impl.ProcessInstanceImpl;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.NodeContainer;
+import org.drools.workflow.core.WorkflowProcess;
+import org.drools.workflow.instance.NodeInstance;
+import org.drools.workflow.instance.NodeInstanceContainer;
+import org.drools.workflow.instance.WorkflowProcessInstance;
+
+/**
+ * Default implementation of a RuleFlow process instance.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public abstract class WorkflowProcessInstanceImpl extends ProcessInstanceImpl
+        implements WorkflowProcessInstance {
+
+    private static final long serialVersionUID = 400L;
+
+    private InternalWorkingMemory workingMemory;
+    private final List<NodeInstance> nodeInstances = new ArrayList<NodeInstance>();;
+    private long nodeInstanceCounter = 0;
+    private List<WorkItemListener> workItemListeners = new ArrayList<WorkItemListener>();
+
+    public WorkflowProcess getWorkflowProcess() {
+        return (WorkflowProcess) getProcess();
+    }
+
+    public NodeContainer getNodeContainer() {
+        return getWorkflowProcess();
+    }
+
+    public void addNodeInstance(final NodeInstance nodeInstance) {
+        ((NodeInstanceImpl) nodeInstance).setId(nodeInstanceCounter++);
+        this.nodeInstances.add(nodeInstance);
+    }
+
+    public void removeNodeInstance(final NodeInstance nodeInstance) {
+        this.nodeInstances.remove(nodeInstance);
+    }
+
+    public Collection<NodeInstance> getNodeInstances() {
+        return getNodeInstances(false);
+    }
+    
+    public Collection<NodeInstance> getNodeInstances(boolean recursive) {
+        Collection<NodeInstance> result = nodeInstances;
+        if (recursive) {
+            result = new ArrayList<NodeInstance>(result);
+            for (Iterator<NodeInstance> iterator = nodeInstances.iterator(); iterator.hasNext(); ) {
+                NodeInstance nodeInstance = iterator.next();
+                if (nodeInstance instanceof NodeInstanceContainer) {
+                    result.addAll(((NodeInstanceContainer) nodeInstance).getNodeInstances(true));
+                }
+            }
+        }
+        return Collections.unmodifiableCollection(result);
+    }
+
+    public NodeInstance getFirstNodeInstance(final long nodeId) {
+        for ( final Iterator<NodeInstance> iterator = this.nodeInstances.iterator(); iterator.hasNext(); ) {
+            final NodeInstance nodeInstance = iterator.next();
+            if ( nodeInstance.getNodeId() == nodeId ) {
+                return nodeInstance;
+            }
+        }
+        return null;
+    }
+
+    public NodeInstance getNodeInstance(final Node node) {
+        NodeInstanceFactoryRegistry nodeRegistry =
+            ((InternalRuleBase) this.workingMemory.getRuleBase())
+                .getConfiguration().getProcessNodeInstanceFactoryRegistry();
+        NodeInstanceFactory conf = nodeRegistry.getProcessNodeInstanceFactory(node);
+        if (conf == null) {
+            throw new IllegalArgumentException("Illegal node type: " + node.getClass());
+        }
+        NodeInstanceImpl nodeInstance = (NodeInstanceImpl) conf.getNodeInstance(node, this, this);
+        nodeInstance.setNodeId(node.getId());
+        nodeInstance.setNodeInstanceContainer(this);
+        nodeInstance.setProcessInstance(this);
+        if (nodeInstance == null) {
+            throw new IllegalArgumentException("Illegal node type: " + node.getClass());
+        }
+        return nodeInstance;
+    }
+
+    public Agenda getAgenda() {
+        if ( this.workingMemory == null ) {
+            return null;
+        }
+        return this.workingMemory.getAgenda();
+    }
+
+    public void setWorkingMemory(final InternalWorkingMemory workingMemory) {
+        if ( this.workingMemory != null ) {
+            throw new IllegalArgumentException( "A working memory can only be set once." );
+        }
+        this.workingMemory = workingMemory;
+    }
+
+    public WorkingMemory getWorkingMemory() {
+        return this.workingMemory;
+    }
+    
+    public void setState(final int state) {
+        super.setState( state );
+        if ( state == ProcessInstanceImpl.STATE_COMPLETED ) {
+            ((EventSupport) this.workingMemory).getRuleFlowEventSupport().fireBeforeRuleFlowProcessCompleted( this,
+                                                                                                              this.workingMemory );
+            // deactivate all node instances of this process instance
+            while ( !nodeInstances.isEmpty() ) {
+                NodeInstance nodeInstance = (NodeInstance) nodeInstances.get( 0 );
+                nodeInstance.cancel();
+            }
+            workingMemory.removeProcessInstance( this );
+            ((EventSupport) this.workingMemory).getRuleFlowEventSupport().fireAfterRuleFlowProcessCompleted( this,
+                                                                                                             this.workingMemory );
+        }
+    }
+
+    public String toString() {
+        final StringBuffer sb = new StringBuffer( "WorkflowProcessInstance" );
+        sb.append( getId() );
+        sb.append( " [processId=" );
+        sb.append( getProcess().getId() );
+        sb.append( ",state=" );
+        sb.append( getState() );
+        sb.append( "]" );
+        return sb.toString();
+    }
+
+    public void workItemCompleted(WorkItem workItem) {
+        for (WorkItemListener listener: workItemListeners) {
+            listener.workItemCompleted(workItem);
+        }
+    }
+
+    public void workItemAborted(WorkItem workItem) {
+        for (WorkItemListener listener: workItemListeners) {
+            listener.workItemCompleted(workItem);
+        }
+    }
+    
+    public void addWorkItemListener(WorkItemListener listener) {
+        workItemListeners.add(listener);
+    }
+    
+    public void removeWorkItemListener(WorkItemListener listener) {
+        workItemListeners.remove(listener);
+    }
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/factory/CreateNewNodeFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/factory/CreateNewNodeFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/factory/CreateNewNodeFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,26 @@
+package org.drools.workflow.instance.impl.factory;
+
+import org.drools.workflow.core.Node;
+import org.drools.workflow.instance.NodeInstance;
+import org.drools.workflow.instance.NodeInstanceContainer;
+import org.drools.workflow.instance.WorkflowProcessInstance;
+import org.drools.workflow.instance.impl.NodeInstanceFactory;
+
+public class CreateNewNodeFactory implements NodeInstanceFactory {
+    
+    public final Class<? extends NodeInstance> cls;
+    
+    public CreateNewNodeFactory(Class<? extends NodeInstance> cls){
+        this.cls = cls;
+    }
+    
+    public NodeInstance getNodeInstance(Node node, WorkflowProcessInstance processInstance, NodeInstanceContainer nodeInstanceContainer ) {     
+        try {
+            return this.cls.newInstance();
+        } catch (Exception e) {
+            throw new RuntimeException("Unable to instantiate node: '"
+                + this.cls.getName() + "':" + e.getMessage());
+        }
+	}
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/factory/ReuseNodeFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/factory/ReuseNodeFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/impl/factory/ReuseNodeFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,30 @@
+package org.drools.workflow.instance.impl.factory;
+
+import org.drools.workflow.core.Node;
+import org.drools.workflow.instance.NodeInstance;
+import org.drools.workflow.instance.NodeInstanceContainer;
+import org.drools.workflow.instance.WorkflowProcessInstance;
+import org.drools.workflow.instance.impl.NodeInstanceFactory;
+
+public class ReuseNodeFactory implements NodeInstanceFactory {
+    
+    public final Class<? extends NodeInstance> cls;
+    
+    public ReuseNodeFactory(Class<? extends NodeInstance> cls){
+        this.cls = cls;
+    }
+
+	public NodeInstance getNodeInstance(Node node, WorkflowProcessInstance processInstance, NodeInstanceContainer nodeInstanceContainer ) {    	
+        NodeInstance result = nodeInstanceContainer.getFirstNodeInstance( node.getId() );
+        if (result != null) {
+            return result;
+        }
+        try {
+            return cls.newInstance();
+        } catch (Exception e) {
+            throw new RuntimeException("Unable to instantiate node '"
+                + this.cls.getName() + "': " + e.getMessage());
+        }
+	}
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/ActionNodeInstance.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/ActionNodeInstance.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/ActionNodeInstance.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,57 @@
+package org.drools.workflow.instance.node;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.Action;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.node.ActionNode;
+import org.drools.workflow.instance.NodeInstance;
+import org.drools.workflow.instance.impl.NodeInstanceImpl;
+
+/**
+ * Runtime counterpart of an action node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class ActionNodeInstance extends NodeInstanceImpl {
+
+    private static final long serialVersionUID = 400L;
+
+    protected ActionNode getActionNode() {
+        return (ActionNode) getNode();
+    }
+
+    public void internalTrigger(final NodeInstance from, String type) {
+        if (!Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
+            throw new IllegalArgumentException(
+                "An ActionNode only accepts default incoming connections!");
+        }
+		Action action = (Action) getActionNode().getAction();
+		try {
+	        action.execute( getProcessInstance().getWorkingMemory() );		    
+		} catch (Exception e) {
+		    throw new RuntimeException("unable to execute Action", e);
+		}
+    	triggerCompleted();
+    }
+
+    public void triggerCompleted() {
+        getNodeInstanceContainer().removeNodeInstance(this);
+        getNodeInstanceContainer().getNodeInstance(getActionNode().getTo().getTo()).trigger(this, getActionNode().getTo().getToType());
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/CompositeNodeInstance.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/CompositeNodeInstance.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/CompositeNodeInstance.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,186 @@
+package org.drools.workflow.instance.node;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.drools.common.InternalRuleBase;
+import org.drools.workflow.core.Connection;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.NodeContainer;
+import org.drools.workflow.core.node.CompositeNode;
+import org.drools.workflow.instance.NodeInstance;
+import org.drools.workflow.instance.NodeInstanceContainer;
+import org.drools.workflow.instance.impl.NodeInstanceFactory;
+import org.drools.workflow.instance.impl.NodeInstanceFactoryRegistry;
+import org.drools.workflow.instance.impl.NodeInstanceImpl;
+
+/**
+ * Runtime counterpart of a composite node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class CompositeNodeInstance extends NodeInstanceImpl implements NodeInstanceContainer {
+
+    private static final long serialVersionUID = 400L;
+    
+    private final List<NodeInstance> nodeInstances = new ArrayList<NodeInstance>();;
+    private long nodeInstanceCounter = 0;
+    
+    protected CompositeNode getCompositeNode() {
+        return (CompositeNode) getNode();
+    }
+    
+    public NodeContainer getNodeContainer() {
+        return getCompositeNode();
+    }
+
+    public void internalTrigger(final NodeInstance from, String type) {
+        CompositeNode.NodeAndType nodeAndType = getCompositeNode().getLinkedIncomingNode(type);
+        List<Connection> connections = nodeAndType.getNode().getIncomingConnections(nodeAndType.getType());
+        for (Iterator<Connection> iterator = connections.iterator(); iterator.hasNext(); ) {
+            Connection connection = iterator.next();
+            if (((CompositeNode.CompositeNodeStart) connection.getFrom()).getInNode().getId() == from.getNodeId()) {
+                NodeInstance nodeInstance = getNodeInstance(connection.getFrom());
+                nodeInstance.trigger(null, nodeAndType.getType());
+                return;
+            }
+        }
+        throw new IllegalArgumentException(
+            "Could not find start for composite node: " + type);
+    }
+
+    public void triggerCompleted(String outType) {
+        getNodeInstanceContainer().removeNodeInstance(this);
+        Connection connection = getCompositeNode().getOutgoingConnections(outType).get(0);
+        getNodeInstanceContainer().getNodeInstance( connection.getTo() ).trigger( this, connection.getToType() );
+    }
+
+    public void addNodeInstance(final NodeInstance nodeInstance) {
+        ((NodeInstanceImpl) nodeInstance).setId(nodeInstanceCounter++);
+        this.nodeInstances.add(nodeInstance);
+    }
+
+    public void removeNodeInstance(final NodeInstance nodeInstance) {
+        this.nodeInstances.remove(nodeInstance);
+    }
+
+    public Collection<NodeInstance> getNodeInstances() {
+        return getNodeInstances(false);
+    }
+    
+    public Collection<NodeInstance> getNodeInstances(boolean recursive) {
+        Collection<NodeInstance> result = nodeInstances;
+        if (recursive) {
+            result = new ArrayList<NodeInstance>(result);
+            for (Iterator<NodeInstance> iterator = nodeInstances.iterator(); iterator.hasNext(); ) {
+                NodeInstance nodeInstance = iterator.next();
+                if (nodeInstance instanceof NodeInstanceContainer) {
+                    result.addAll(((NodeInstanceContainer) nodeInstance).getNodeInstances(true));
+                }
+            }
+        }
+        return Collections.unmodifiableCollection(result);
+    }
+
+    public NodeInstance getFirstNodeInstance(final long nodeId) {
+        for ( final Iterator<NodeInstance> iterator = this.nodeInstances.iterator(); iterator.hasNext(); ) {
+            final NodeInstance nodeInstance = iterator.next();
+            if ( nodeInstance.getNodeId() == nodeId ) {
+                return nodeInstance;
+            }
+        }
+        return null;
+    }
+    
+    public NodeInstance getNodeInstance(final Node node) {
+        // TODO do this cleaner for start / end of composite?
+        if (node instanceof CompositeNode.CompositeNodeStart) {
+            CompositeNodeStartInstance nodeInstance = new CompositeNodeStartInstance();
+            nodeInstance.setNodeId(node.getId());
+            nodeInstance.setNodeInstanceContainer(this);
+            nodeInstance.setProcessInstance(getProcessInstance());
+            return nodeInstance;
+        } else if (node instanceof CompositeNode.CompositeNodeEnd) {
+            CompositeNodeEndInstance nodeInstance = new CompositeNodeEndInstance();
+            nodeInstance.setNodeId(node.getId());
+            nodeInstance.setNodeInstanceContainer(this);
+            nodeInstance.setProcessInstance(getProcessInstance());
+            return nodeInstance;
+        }
+        
+        NodeInstanceFactoryRegistry nodeRegistry =
+            ((InternalRuleBase) getProcessInstance().getWorkingMemory().getRuleBase())
+                .getConfiguration().getProcessNodeInstanceFactoryRegistry();
+        NodeInstanceFactory conf = nodeRegistry.getProcessNodeInstanceFactory(node);
+        if (conf == null) {
+            throw new IllegalArgumentException("Illegal node type: " + node.getClass());
+        }
+        NodeInstanceImpl nodeInstance = (NodeInstanceImpl) conf.getNodeInstance(node, getProcessInstance(), this);
+        nodeInstance.setNodeId(node.getId());
+        nodeInstance.setNodeInstanceContainer(this);
+        nodeInstance.setProcessInstance(getProcessInstance());
+        if (nodeInstance == null) {
+            throw new IllegalArgumentException("Illegal node type: " + node.getClass());
+        }
+        return nodeInstance;
+    }
+
+    public class CompositeNodeStartInstance extends NodeInstanceImpl {
+
+        private static final long serialVersionUID = 400L;
+
+        public CompositeNode.CompositeNodeStart getCompositeNodeStart() {
+            return (CompositeNode.CompositeNodeStart) getNode();
+        }
+        
+        public void internalTrigger(NodeInstance from, String type) {
+            triggerCompleted();
+        }
+        
+        public void triggerCompleted() {
+            getNodeInstanceContainer().removeNodeInstance(this);
+            getNodeInstanceContainer().getNodeInstance( getCompositeNodeStart().getTo().getTo() ).trigger( this, getCompositeNodeStart().getTo().getToType());
+        }
+        
+    }
+
+    public class CompositeNodeEndInstance extends NodeInstanceImpl {
+
+        private static final long serialVersionUID = 400L;
+
+        public CompositeNode.CompositeNodeEnd getCompositeNodeEnd() {
+            return (CompositeNode.CompositeNodeEnd) getNode();
+        }
+        
+        public void internalTrigger(NodeInstance from, String type) {
+            triggerCompleted();
+        }
+        
+        public void triggerCompleted() {
+            getNodeInstanceContainer().removeNodeInstance(this);
+            CompositeNodeInstance.this.triggerCompleted(
+                getCompositeNodeEnd().getOutType());
+        }
+        
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/EndNodeInstance.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/EndNodeInstance.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/EndNodeInstance.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,42 @@
+package org.drools.workflow.instance.node;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.process.instance.ProcessInstance;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.instance.NodeInstance;
+import org.drools.workflow.instance.impl.NodeInstanceImpl;
+
+/**
+ * Runtime counterpart of an end node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class EndNodeInstance extends NodeInstanceImpl {
+
+    private static final long serialVersionUID = 400L;
+
+    public void internalTrigger(final NodeInstance from, String type) {
+        if (!Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
+            throw new IllegalArgumentException(
+                "An EndNode only accepts default incoming connections!");
+        }
+        getNodeInstanceContainer().removeNodeInstance(this);
+        getProcessInstance().setState( ProcessInstance.STATE_COMPLETED );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/JoinInstance.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/JoinInstance.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/JoinInstance.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,121 @@
+package org.drools.workflow.instance.node;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.drools.workflow.core.Connection;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.node.Join;
+import org.drools.workflow.instance.NodeInstance;
+import org.drools.workflow.instance.impl.NodeInstanceImpl;
+
+/**
+ * Runtime counterpart of a join node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class JoinInstance extends NodeInstanceImpl {
+
+    private static final long serialVersionUID = 400L;
+    
+    private final Map<Node, Integer> triggers = new HashMap<Node, Integer>();
+    
+    protected Join getJoin() {
+        return (Join) getNode();
+    }
+
+    public void internalTrigger(final NodeInstance from, String type) {
+        if (!Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
+            throw new IllegalArgumentException(
+                "An ActionNode only accepts default incoming connections!");
+        }
+        final Join join = getJoin();
+        switch ( join.getType() ) {
+            case Join.TYPE_XOR :
+                triggerCompleted();
+                break;
+            case Join.TYPE_AND :
+                Node node = getNodeInstanceContainer().getNodeContainer().getNode( from.getNodeId() );
+                Integer count = (Integer) this.triggers.get( node );
+                if ( count == null ) {
+                    this.triggers.put( node,
+                                       new Integer( 1 ) );
+                } else {
+                    this.triggers.put( node,
+                                       new Integer( count.intValue() + 1 ) );
+                }
+                if (checkAllActivated()) {
+                    decreaseAllTriggers();
+                    triggerCompleted();
+                }
+                break;
+            case Join.TYPE_DISCRIMINATOR :
+                boolean triggerCompleted = triggers.isEmpty();
+                node = getNodeInstanceContainer().getNodeContainer().getNode( from.getNodeId() );
+                triggers.put( node, new Integer( 1 ) );
+                if (checkAllActivated()) {
+                    resetAllTriggers();
+                }
+                if (triggerCompleted) {
+                    triggerCompleted();
+                }
+                break;
+            default :
+                throw new IllegalArgumentException( "Illegal join type " + join.getType() );
+        }
+    }
+
+    private boolean checkAllActivated() {
+        // check whether all parent nodes have been triggered 
+        for ( final Iterator<Connection> it = getJoin().getDefaultIncomingConnections().iterator(); it.hasNext(); ) {
+            final Connection connection = it.next();
+            if ( this.triggers.get( connection.getFrom() ) == null ) {
+                return false;
+            }
+        }
+        return true;
+    }
+    
+    private void decreaseAllTriggers() {
+        // decrease trigger count for all incoming connections
+        for ( final Iterator<Connection> it = getJoin().getDefaultIncomingConnections().iterator(); it.hasNext(); ) {
+            final Connection connection = it.next();
+            final Integer count = (Integer) this.triggers.get( connection.getFrom() );
+            if ( count.intValue() == 1 ) {
+                this.triggers.remove( connection.getFrom() );
+            } else {
+                this.triggers.put( connection.getFrom(),
+                                   new Integer( count.intValue() - 1 ) );
+            }
+        }
+    }
+
+    private void resetAllTriggers() {
+        triggers.clear();
+    }
+
+    public void triggerCompleted() {
+        // join nodes are only removed from the container when they contain no more state
+        if (triggers.isEmpty()) {
+            getNodeInstanceContainer().removeNodeInstance(this);
+        }
+        getNodeInstanceContainer().getNodeInstance( getJoin().getTo().getTo() ).trigger( this, getJoin().getTo().getToType() );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/MilestoneNodeInstance.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/MilestoneNodeInstance.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/MilestoneNodeInstance.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,115 @@
+package org.drools.workflow.instance.node;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Iterator;
+
+import org.drools.WorkingMemory;
+import org.drools.common.RuleFlowGroupNode;
+import org.drools.event.ActivationCancelledEvent;
+import org.drools.event.ActivationCreatedEvent;
+import org.drools.event.AfterActivationFiredEvent;
+import org.drools.event.AgendaEventListener;
+import org.drools.event.AgendaGroupPoppedEvent;
+import org.drools.event.AgendaGroupPushedEvent;
+import org.drools.event.BeforeActivationFiredEvent;
+import org.drools.spi.Activation;
+import org.drools.spi.RuleFlowGroup;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.node.MilestoneNode;
+import org.drools.workflow.instance.NodeInstance;
+import org.drools.workflow.instance.impl.NodeInstanceImpl;
+
+/**
+ * Runtime counterpart of a milestone node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class MilestoneNodeInstance extends NodeInstanceImpl implements AgendaEventListener {
+
+    private static final long serialVersionUID = 400L;
+
+    protected MilestoneNode getMilestoneNode() {
+        return (MilestoneNode) getNode();
+    }
+
+    public void internalTrigger(final NodeInstance from, String type) {
+        if (!Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
+            throw new IllegalArgumentException(
+                "A MilestoneNode only accepts default incoming connections!");
+        }
+    	RuleFlowGroup systemRuleFlowGroup = getProcessInstance().getAgenda().getRuleFlowGroup("DROOLS_SYSTEM");
+    	String rule = "RuleFlow-Milestone-" + getProcessInstance().getProcess().getId()
+    		+ "-" + getNode().getId();
+    	for (Iterator activations = systemRuleFlowGroup.iterator(); activations.hasNext(); ) {
+    		Activation activation = ((RuleFlowGroupNode) activations.next()).getActivation();
+    		if (rule.equals(activation.getRule().getName())) {
+    			triggerCompleted();
+        		return;
+    		}
+    	}
+    	getProcessInstance().getWorkingMemory().addEventListener(this);
+    }
+
+    public void triggerCompleted() {
+        getNodeInstanceContainer().removeNodeInstance(this);
+        getNodeInstanceContainer().getNodeInstance(getMilestoneNode().getTo().getTo())
+            .trigger(this, getMilestoneNode().getTo().getToType());
+    }
+
+    public void activationCancelled(ActivationCancelledEvent event,
+            WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+    public void activationCreated(ActivationCreatedEvent event,
+            WorkingMemory workingMemory) {
+        // check whether this activation is from the DROOLS_SYSTEM agenda group
+        String ruleFlowGroup = event.getActivation().getRule().getRuleFlowGroup();
+        if ("DROOLS_SYSTEM".equals(ruleFlowGroup)) {
+            // new activations of the rule associate with a milestone node
+            // trigger node instances of that milestone node
+            String ruleName = event.getActivation().getRule().getName();
+            String milestoneName = "RuleFlow-Milestone-" + getProcessInstance().getProcess().getId() + "-" + getNodeId();
+            if (milestoneName.equals(ruleName)) {
+                getProcessInstance().getWorkingMemory().removeEventListener(this);
+                triggerCompleted();
+            }
+        }
+    }
+
+    public void afterActivationFired(AfterActivationFiredEvent event,
+            WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+    public void agendaGroupPopped(AgendaGroupPoppedEvent event,
+            WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+    public void agendaGroupPushed(AgendaGroupPushedEvent event,
+            WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+    public void beforeActivationFired(BeforeActivationFiredEvent event,
+            WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/RuleSetNodeInstance.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/RuleSetNodeInstance.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/RuleSetNodeInstance.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,71 @@
+package org.drools.workflow.instance.node;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.common.InternalRuleFlowGroup;
+import org.drools.common.RuleFlowGroupListener;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.node.RuleSetNode;
+import org.drools.workflow.instance.NodeInstance;
+import org.drools.workflow.instance.impl.NodeInstanceImpl;
+
+/**
+ * Runtime counterpart of a ruleset node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class RuleSetNodeInstance extends NodeInstanceImpl implements RuleFlowGroupListener {
+
+    private static final long serialVersionUID = 400L;
+    
+    private InternalRuleFlowGroup ruleFlowGroup;
+
+    public RuleSetNodeInstance() {
+    }
+    
+    protected RuleSetNode getRuleSetNode() {
+        return (RuleSetNode) getNode();
+    }
+
+    public void internalTrigger(final NodeInstance from, String type) {
+        ruleFlowGroup = (InternalRuleFlowGroup)
+        getProcessInstance().getWorkingMemory().getAgenda()
+            .getRuleFlowGroup(getRuleSetNode().getRuleFlowGroup());
+        ruleFlowGroup.addRuleFlowGroupListener(this);
+        if (!Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
+            throw new IllegalArgumentException(
+                "A RuleSetNode only accepts default incoming connections!");
+        }
+        getProcessInstance().getAgenda().activateRuleFlowGroup( getRuleSetNode().getRuleFlowGroup() );
+    }
+
+    public void triggerCompleted() {
+        getNodeInstanceContainer().removeNodeInstance(this);
+        getNodeInstanceContainer().getNodeInstance( getRuleSetNode().getTo().getTo() ).trigger( this, getRuleSetNode().getTo().getToType() );
+    }
+    
+    public void cancel() {
+    	getProcessInstance().getAgenda().deactivateRuleFlowGroup( getRuleSetNode().getRuleFlowGroup() );
+    	super.cancel();
+    }
+
+    public void ruleFlowGroupDeactivated() {
+        ruleFlowGroup.removeRuleFlowGroupListener(this);
+        triggerCompleted();
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/SplitInstance.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/SplitInstance.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/SplitInstance.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,118 @@
+package org.drools.workflow.instance.node;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.drools.workflow.core.Connection;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.node.Split;
+import org.drools.workflow.instance.NodeInstance;
+import org.drools.workflow.instance.impl.ConstraintEvaluator;
+import org.drools.workflow.instance.impl.NodeInstanceImpl;
+
+/**
+ * Runtime counterpart of a split node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class SplitInstance extends NodeInstanceImpl {
+
+    private static final long serialVersionUID = 400L;
+
+    protected Split getSplit() {
+        return (Split) getNode();
+    }
+
+    public void internalTrigger(final NodeInstance from, String type) {
+        if (!Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
+            throw new IllegalArgumentException(
+                "A Split only accepts default incoming connections!");
+        }
+        final Split split = getSplit();
+        // TODO make different strategies for each type
+        switch ( split.getType() ) {
+            case Split.TYPE_AND :
+                getNodeInstanceContainer().removeNodeInstance(this);
+                List<Connection> outgoing = split.getDefaultOutgoingConnections();
+                for ( final Iterator<Connection> iterator = outgoing.iterator(); iterator.hasNext(); ) {
+                    final Connection connection = (Connection) iterator.next();
+                    getNodeInstanceContainer().getNodeInstance(connection.getTo()).trigger(this, connection.getToType());
+                }
+                break;
+            case Split.TYPE_XOR :
+                outgoing = split.getDefaultOutgoingConnections();
+                int priority = Integer.MAX_VALUE;
+                Connection selected = null;
+                for ( final Iterator<Connection> iterator = outgoing.iterator(); iterator.hasNext(); ) {
+                    final Connection connection = (Connection) iterator.next();
+                    ConstraintEvaluator constraint = (ConstraintEvaluator) split.getConstraint( connection );
+                    if ( constraint != null && constraint.getPriority() < priority ) {
+                        if ( constraint.evaluate( this,
+                                                  connection,
+                                                  constraint ) ) {
+                            selected = connection;
+                            priority = constraint.getPriority();
+                            break;
+                        }
+                    }
+                }
+                getNodeInstanceContainer().removeNodeInstance(this);
+                if ( selected == null ) {
+                    throw new IllegalArgumentException( "XOR split could not find at least one valid outgoing connection for split " + getSplit().getName() );
+                }
+                getNodeInstanceContainer().getNodeInstance( selected.getTo() ).trigger( this, selected.getToType() );
+                break;
+            case Split.TYPE_OR :
+                getNodeInstanceContainer().removeNodeInstance(this);
+                outgoing = split.getDefaultOutgoingConnections();
+                boolean found = false;
+                List<Connection> outgoingCopy = new ArrayList<Connection>(outgoing);
+                while (!outgoingCopy.isEmpty()) {
+                    priority = Integer.MAX_VALUE;
+                    Connection selectedConnection = null;
+                    ConstraintEvaluator selectedConstraint = null;
+                    for ( final Iterator<Connection> iterator = outgoingCopy.iterator(); iterator.hasNext(); ) {
+                        final Connection connection = (Connection) iterator.next();
+                        ConstraintEvaluator constraint = (ConstraintEvaluator) split.getConstraint( connection );
+    
+                        if ( constraint != null  
+                                && constraint.getPriority() < priority ) {
+                            priority = constraint.getPriority();
+                            selectedConnection = connection;
+                            selectedConstraint = constraint;
+                        }
+                    }
+                    if (selectedConstraint.evaluate( this,
+                                                     selectedConnection,
+                                                     selectedConstraint ) ) {
+                            getNodeInstanceContainer().getNodeInstance(selectedConnection.getTo()).trigger(this, selectedConnection.getToType());
+                            found = true;
+                    }
+                    outgoingCopy.remove(selectedConnection);
+                }
+                if ( !found ) {
+                    throw new IllegalArgumentException( "OR split could not find at least one valid outgoing connection for split " + getSplit().getName() );
+                }                
+                break;
+            default :
+                throw new IllegalArgumentException( "Illegal split type " + split.getType() );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/StartNodeInstance.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/StartNodeInstance.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/StartNodeInstance.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,54 @@
+package org.drools.workflow.instance.node;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.workflow.core.node.StartNode;
+import org.drools.workflow.instance.NodeInstance;
+import org.drools.workflow.instance.impl.NodeInstanceImpl;
+
+/**
+ * Runtime counterpart of a start node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class StartNodeInstance extends NodeInstanceImpl {
+
+    private static final long serialVersionUID = 400L;
+
+    public void internalTrigger(final NodeInstance from, String type) {
+        if (type != null) {
+            throw new IllegalArgumentException(
+                "A StartNode does not accept incoming connections!");
+        }
+        if (from != null) {
+            throw new IllegalArgumentException(
+                "A StartNode can only be triggered by the process itself!");
+        }
+        triggerCompleted();
+    }
+    
+    public StartNode getStartNode() {
+        return (StartNode) getNode();
+    }
+
+    public void triggerCompleted() {
+        getNodeInstanceContainer().removeNodeInstance(this);
+        getNodeInstanceContainer().getNodeInstance(getStartNode().getTo().getTo())
+            .trigger(this, getStartNode().getTo().getToType());
+    }
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/SubProcessNodeInstance.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/SubProcessNodeInstance.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/SubProcessNodeInstance.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,126 @@
+package org.drools.workflow.instance.node;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.WorkingMemory;
+import org.drools.event.RuleFlowCompletedEvent;
+import org.drools.event.RuleFlowEventListener;
+import org.drools.event.RuleFlowGroupActivatedEvent;
+import org.drools.event.RuleFlowGroupDeactivatedEvent;
+import org.drools.event.RuleFlowNodeTriggeredEvent;
+import org.drools.event.RuleFlowStartedEvent;
+import org.drools.process.instance.ProcessInstance;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.node.SubProcessNode;
+import org.drools.workflow.instance.NodeInstance;
+import org.drools.workflow.instance.impl.NodeInstanceImpl;
+
+/**
+ * Runtime counterpart of a SubFlow node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class SubProcessNodeInstance extends NodeInstanceImpl implements RuleFlowEventListener {
+
+    private static final long serialVersionUID = 400L;
+    
+    private long processInstanceId;
+	
+    protected SubProcessNode getSubFlowNode() {
+        return (SubProcessNode) getNode();
+    }
+
+    public void internalTrigger(final NodeInstance from, String type) {
+        if (!Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
+            throw new IllegalArgumentException(
+                "A SubProcess node only accepts default incoming connections!");
+        }
+    	ProcessInstance processInstance = 
+    		getProcessInstance().getWorkingMemory().startProcess(getSubFlowNode().getProcessId());
+    	if (!getSubFlowNode().isWaitForCompletion()
+    	        || processInstance.getState() == ProcessInstance.STATE_COMPLETED) {
+    		triggerCompleted();
+    	} else {
+    	    getProcessInstance().getWorkingMemory().addEventListener(this);
+    		this.processInstanceId = processInstance.getId();
+    	}
+    }
+    
+    public long getProcessInstanceId() {
+    	return processInstanceId;
+    }
+
+    public void triggerCompleted() {
+        getNodeInstanceContainer().removeNodeInstance(this);
+        getNodeInstanceContainer().getNodeInstance(getSubFlowNode().getTo().getTo())
+            .trigger(this, getSubFlowNode().getTo().getToType());
+    }
+
+    public void afterRuleFlowCompleted(RuleFlowCompletedEvent event,
+            WorkingMemory workingMemory) {
+        if ( event.getRuleFlowProcessInstance().getId() == processInstanceId ) {
+            getProcessInstance().getWorkingMemory().removeEventListener(this);
+            triggerCompleted();
+        }
+    }
+
+    public void afterRuleFlowGroupActivated(RuleFlowGroupActivatedEvent event,
+            WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+    public void afterRuleFlowGroupDeactivated(
+            RuleFlowGroupDeactivatedEvent event, WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+    public void afterRuleFlowNodeTriggered(RuleFlowNodeTriggeredEvent event,
+            WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+    public void afterRuleFlowStarted(RuleFlowStartedEvent event,
+            WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+    public void beforeRuleFlowCompleted(RuleFlowCompletedEvent event,
+            WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+    public void beforeRuleFlowGroupActivated(RuleFlowGroupActivatedEvent event,
+            WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+    public void beforeRuleFlowGroupDeactivated(
+            RuleFlowGroupDeactivatedEvent event, WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+    public void beforeRuleFlowNodeTriggered(RuleFlowNodeTriggeredEvent event,
+            WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+    public void beforeRuleFlowStarted(RuleFlowStartedEvent event,
+            WorkingMemory workingMemory) {
+        // Do nothing
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/WorkItemNodeInstance.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/WorkItemNodeInstance.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/java/org/drools/workflow/instance/node/WorkItemNodeInstance.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,92 @@
+package org.drools.workflow.instance.node;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Iterator;
+import java.util.Map;
+
+import org.drools.process.core.Work;
+import org.drools.process.instance.WorkItem;
+import org.drools.process.instance.WorkItemListener;
+import org.drools.process.instance.impl.WorkItemImpl;
+import org.drools.workflow.core.node.WorkItemNode;
+import org.drools.workflow.instance.NodeInstance;
+import org.drools.workflow.instance.impl.NodeInstanceImpl;
+
+/**
+ * Runtime counterpart of a task node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class WorkItemNodeInstance extends NodeInstanceImpl implements WorkItemListener {
+
+    private static final long serialVersionUID = 400L;
+    
+    private WorkItemImpl workItem;
+    
+    protected WorkItemNode getWorkItemNode() {
+        return (WorkItemNode) getNode();
+    }
+    
+    public WorkItem getWorkItem() {
+        return workItem;
+    }
+
+    public void internalTrigger(final NodeInstance from, String type) {
+        // TODO this should be included for ruleflow only, not for BPEL
+//        if (!Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
+//            throw new IllegalArgumentException(
+//                "A WorkItemNode only accepts default incoming connections!");
+//        }
+        WorkItemNode workItemNode = getWorkItemNode();
+        Work work = workItemNode.getWork();
+		workItem = new WorkItemImpl();
+		workItem.setName(work.getName());
+		workItem.setProcessInstanceId(getProcessInstance().getId());
+		workItem.setParameters(work.getParameters());
+		for (Iterator<Map.Entry<String, String>> iterator = workItemNode.getInMappings().entrySet().iterator(); iterator.hasNext(); ) {
+            Map.Entry<String, String> mapping = iterator.next();
+            workItem.setParameter(mapping.getKey(), getProcessInstance().getVariable(mapping.getValue()));
+        }
+		getProcessInstance().addWorkItemListener(this);
+		getProcessInstance().getWorkingMemory().getWorkItemManager().executeWorkItem(workItem);
+    }
+
+    public void triggerCompleted(WorkItem workItem) {
+        getNodeInstanceContainer().removeNodeInstance(this);
+        for (Iterator<Map.Entry<String, String>> iterator = getWorkItemNode().getOutMappings().entrySet().iterator(); iterator.hasNext(); ) {
+            Map.Entry<String, String> mapping = iterator.next();
+            getProcessInstance().setVariable(mapping.getValue(), workItem.getResult(mapping.getKey()));
+        }
+        getNodeInstanceContainer().getNodeInstance( getWorkItemNode().getTo().getTo() ).trigger( this, getWorkItemNode().getTo().getToType() );
+    }
+
+    public void workItemAborted(WorkItem workItem) {
+        if ( this.workItem.getId() == workItem.getId() ) {
+            getProcessInstance().removeWorkItemListener(this);
+            triggerCompleted(workItem);
+        }
+    }
+
+    public void workItemCompleted(WorkItem workItem) {
+        if ( this.workItem.getId() == workItem.getId() ) {
+            getProcessInstance().removeWorkItemListener(this);
+            triggerCompleted(workItem);
+        }
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/META-INF/drools.default.rulebase.conf
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/META-INF/drools.default.rulebase.conf	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/META-INF/drools.default.rulebase.conf	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,19 @@
+drools.maintainTms = true
+drools.shadowproxy = true
+drools.shadowproxy.exclude =
+drools.sequential = false
+drools.sequential.agenda = sequential
+drools.removeIdentities = false
+drools.shareAlphaNodes = true
+drools.shareBetaNodes = true
+drools.alphaMemory = false
+drools.alphaNodeHashingThreshold = 3
+drools.compositeKeyDepth = 3
+drools.indexLeftBetaMemory = true
+drools.indexRightBetaMemory = true
+drools.assertBehaviour = IDENTITY
+drools.logicalOverride = DISCARD
+drools.executorService = org.drools.concurrent.DefaultExecutorService
+drools.conflictResolver = org.drools.conflict.DepthConflictResolver
+drools.consequenceExceptionHandler = org.drools.base.DefaultConsequenceExceptionHandler
+drools.ruleBaseUpdateHandler = org.drools.base.FireAllRulesRuleBaseUpdateListener

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/audit/package.html
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/audit/package.html	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/audit/package.html	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,3 @@
+<body>
+	This is a utility for providing audit trails/explanations of rule actions.
+</body>
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/event/package.html
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/event/package.html	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/event/package.html	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,3 @@
+<body>
+	Events provide all sorts of call backs to monitor the engine as it is running.
+</body>
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/package.html
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/package.html	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/package.html	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,3 @@
+<body>
+	This is the engine that works off binary RuleBases, you will mostly use WorkingMemory, RuleBase and RuleBaseFactory
+</body>
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/rule/package.html
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/rule/package.html	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/rule/package.html	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,3 @@
+<body>
+	Contains the binary representations of rule constructs, like Package (which the compiler produces), Rule, and Conditional Elements.
+</body>
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/visualize/package.html
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/visualize/package.html	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/org/drools/visualize/package.html	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,3 @@
+<body>
+	Some visual utilities for viewing RETE networks (can also use the plug in for this)
+</body>
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/overview.html
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/overview.html	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/main/resources/overview.html	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,22 @@
+<body>
+
+<h2>Drools API</h2>
+<P/>
+The documentation concentrates upon the following key interfaces:
+<li><tt>org.drools.WorkingMemory</tt></li>
+<li><tt>org.drools.RuleBase</tt></li>
+<li><tt>org.drools.RuleBaseFactory</tt></li>
+<li><tt>org.drools.compiler.PackageBuilder</tt></li>
+<li><tt>org.drools.compiler.RuleBaseLoader</tt></li>
+<li><tt>org.drools.rule.Package</tt></li>
+
+These interfaces are fully intended to be exposed to application code.
+Gernally speaking, PackageBuilder would be used to assemble binary rule Packages, which are what is used by the 
+core engine (RuleBase, WorkingMemory).<br>
+
+<br>
+The other utility classes are optional, and you may or may not need to use them based on your specific needs.
+<br>
+The Internal APIs are not intended for "normal" application code use, but from time to time, advanced uses may need to refer to or use this API directly.
+
+</body>
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/codehaus/jfdi/interpreter/ClassTypeResolverTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/codehaus/jfdi/interpreter/ClassTypeResolverTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/codehaus/jfdi/interpreter/ClassTypeResolverTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,201 @@
+/**
+ *
+ */
+package org.codehaus.jfdi.interpreter;
+
+import java.util.HashSet;
+
+import junit.framework.TestCase;
+
+import org.drools.Cheese;
+import org.drools.FirstClass;
+import org.drools.SecondClass;
+import org.drools.base.ClassTypeResolver;
+import org.drools.base.TypeResolver;
+
+/**
+ * @author fburlet
+ *
+ */
+public class ClassTypeResolverTest extends TestCase {
+
+    public void testResolvePrimtiveTypes() throws Exception {
+        final ClassTypeResolver resolver = new ClassTypeResolver(new HashSet(), Thread.currentThread().getContextClassLoader());
+        assertEquals( boolean.class,
+                      resolver.resolveType( "boolean" ) );
+        assertEquals( double.class,
+                      resolver.resolveType( "double" ) );
+        assertEquals( float.class,
+                      resolver.resolveType( "float" ) );
+        assertEquals( int.class,
+                      resolver.resolveType( "int" ) );
+        assertEquals( char.class,
+                      resolver.resolveType( "char" ) );
+        assertEquals( long.class,
+                      resolver.resolveType( "long" ) );
+        assertEquals( byte.class,
+                      resolver.resolveType( "byte" ) );
+        assertEquals( short.class,
+                      resolver.resolveType( "short" ) );
+    }
+
+    public void testResolveArrayOfPrimitiveTypes() throws Exception {
+        final ClassTypeResolver resolver =  new ClassTypeResolver(new HashSet(), Thread.currentThread().getContextClassLoader());
+        assertEquals( boolean[].class,
+                      resolver.resolveType( "boolean[]" ) );
+        assertEquals( double[].class,
+                      resolver.resolveType( "double[]" ) );
+        assertEquals( float[].class,
+                      resolver.resolveType( "float[]" ) );
+        assertEquals( int[].class,
+                      resolver.resolveType( "int[]" ) );
+        assertEquals( char[].class,
+                      resolver.resolveType( "char[]" ) );
+        assertEquals( long[].class,
+                      resolver.resolveType( "long[]" ) );
+        assertEquals( byte[].class,
+                      resolver.resolveType( "byte[]" ) );
+        assertEquals( short[].class,
+                      resolver.resolveType( "short[]" ) );
+    }
+
+    public void testResolveMultidimensionnalArrayOfPrimitiveTypes() throws Exception {
+        final ClassTypeResolver resolver =  new ClassTypeResolver(new HashSet(), Thread.currentThread().getContextClassLoader());
+        assertEquals( int[][].class,
+                      resolver.resolveType( "int[][]" ) );
+        assertEquals( int[][][].class,
+                      resolver.resolveType( "int[][][]" ) );
+        assertEquals( int[][][][].class,
+                      resolver.resolveType( "int[][][][]" ) );
+    }
+
+    public void testResolveObjectNotFromImport() throws Exception {
+        final ClassTypeResolver resolver =  new ClassTypeResolver(new HashSet(), Thread.currentThread().getContextClassLoader());
+        assertEquals( String.class,
+                      resolver.resolveType( "String" ) );
+        assertEquals( String.class,
+                      resolver.resolveType( "java.lang.String" ) );
+        try {
+            assertEquals( Cheese.class,
+                          resolver.resolveType( "Cheese" ) );
+            fail( "Should raise a ClassNotFoundException" );
+        } catch ( final ClassNotFoundException e ) {
+            // success
+        }
+        assertEquals( Cheese.class,
+                      resolver.resolveType( "org.drools.Cheese" ) );
+    }
+
+    public void testResolveObjectFromImport() throws Exception {
+        final ClassTypeResolver resolver = new ClassTypeResolver( new HashSet(), Thread.currentThread().getContextClassLoader() );
+        resolver.addImport( "org.drools.Cheese" );
+        resolver.addImport( "org.drools.FirstClass" );
+        resolver.addImport( "org.drools.FirstClass.AlternativeKey" );
+        resolver.addImport( "org.drools.SecondClass" );
+        resolver.addImport( "org.drools.SecondClass.AlternativeKey" );
+
+        assertEquals( String.class,
+                      resolver.resolveType( "String" ) );
+        assertEquals( String.class,
+                      resolver.resolveType( "java.lang.String" ) );
+        assertEquals( Cheese.class,
+                      resolver.resolveType( "Cheese" ) );
+        assertEquals( Cheese.class,
+                      resolver.resolveType( "org.drools.Cheese" ) );
+        assertEquals( FirstClass.class,
+                      resolver.resolveType( "org.drools.FirstClass" ) );
+        assertEquals( FirstClass.AlternativeKey.class,
+                      resolver.resolveType( "org.drools.FirstClass.AlternativeKey" ) );
+
+        assertEquals( SecondClass.class,
+                      resolver.resolveType( "org.drools.SecondClass" ) );
+        assertEquals( SecondClass.AlternativeKey.class,
+                      resolver.resolveType( "org.drools.SecondClass.AlternativeKey" ) );
+    }
+
+    public void testResolveFullTypeName() throws Exception {
+
+        final TypeResolver resolver = new ClassTypeResolver( new HashSet(), Thread.currentThread().getContextClassLoader() );
+        resolver.addImport( "org.drools.Cheese" );
+        resolver.addImport( "org.drools.FirstClass" );
+
+        assertEquals("org.drools.Cheese", resolver.getFullTypeName("Cheese"));
+        assertEquals("org.drools.FirstClass", resolver.getFullTypeName("FirstClass"));
+
+
+
+    }
+
+    public void testResolveObjectFromImportMultipleClassesDifferentPackages() throws Exception {
+        final ClassTypeResolver resolver = new ClassTypeResolver( new HashSet(), Thread.currentThread().getContextClassLoader() );
+        resolver.addImport( "org.drools.Cheese" );
+        assertEquals( String.class,
+                      resolver.resolveType( "String" ) );
+        assertEquals( String.class,
+                      resolver.resolveType( "java.lang.String" ) );
+        assertEquals( Cheese.class,
+                      resolver.resolveType( "Cheese" ) );
+        assertEquals( Cheese.class,
+                      resolver.resolveType( "org.drools.Cheese" ) );
+    }
+
+    public void testResolveArrayOfObjectsNotFromImport() throws Exception {
+        final ClassTypeResolver resolver =  new ClassTypeResolver(new HashSet(), Thread.currentThread().getContextClassLoader());
+        assertEquals( String[].class,
+                      resolver.resolveType( "String[]" ) );
+        assertEquals( String[].class,
+                      resolver.resolveType( "java.lang.String[]" ) );
+        try {
+            assertEquals( Cheese[].class,
+                          resolver.resolveType( "Cheese[]" ) );
+            fail( "Should raise a ClassNotFoundException" );
+        } catch ( final ClassNotFoundException e ) {
+            // success
+        }
+        assertEquals( Cheese[].class,
+                      resolver.resolveType( "org.drools.Cheese[]" ) );
+    }
+
+    public void testResolveArrayOfObjectsFromImport() throws Exception {
+        final ClassTypeResolver resolver = new ClassTypeResolver( new HashSet(), Thread.currentThread().getContextClassLoader() );
+        resolver.addImport( "org.drools.Cheese" );
+        assertEquals( String[].class,
+                      resolver.resolveType( "String[]" ) );
+        assertEquals( String[].class,
+                      resolver.resolveType( "java.lang.String[]" ) );
+        assertEquals( Cheese[].class,
+                      resolver.resolveType( "Cheese[]" ) );
+        assertEquals( Cheese[].class,
+                      resolver.resolveType( "org.drools.Cheese[]" ) );
+    }
+
+    public void testResolveMultidimensionnalArrayOfObjectsNotFromImport() throws Exception {
+        final ClassTypeResolver resolver =  new ClassTypeResolver(new HashSet(), Thread.currentThread().getContextClassLoader());
+        assertEquals( String[][].class,
+                      resolver.resolveType( "String[][]" ) );
+        assertEquals( String[][].class,
+                      resolver.resolveType( "java.lang.String[][]" ) );
+        try {
+            assertEquals( Cheese[][].class,
+                          resolver.resolveType( "Cheese[][]" ) );
+            fail( "Should raise a ClassNotFoundException" );
+        } catch ( final ClassNotFoundException e ) {
+            // success
+        }
+        assertEquals( Cheese[][].class,
+                      resolver.resolveType( "org.drools.Cheese[][]" ) );
+    }
+
+    public void testResolveMultidimensionnalArrayOfObjectsFromImport() throws Exception {
+        final ClassTypeResolver resolver = new ClassTypeResolver( new HashSet(), Thread.currentThread().getContextClassLoader() );
+        resolver.addImport( "org.drools.Cheese" );
+        assertEquals( String[][].class,
+                      resolver.resolveType( "String[][]" ) );
+        assertEquals( String[][].class,
+                      resolver.resolveType( "java.lang.String[][]" ) );
+        assertEquals( Cheese[][].class,
+                      resolver.resolveType( "Cheese[][]" ) );
+        assertEquals( Cheese[][].class,
+                      resolver.resolveType( "org.drools.Cheese[][]" ) );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/Address.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/Address.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/Address.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,40 @@
+package org.drools;
+
+public class Address {
+    
+    private String street;
+    private String number;
+    private String phone;
+    
+    public Address() {}
+    
+    public Address( String street, String number, String phone ) {
+        this.street = street;
+        this.number = number;
+        this.phone  = phone;
+    }
+    
+    public String getNumber() {
+        return number;
+    }
+    public void setNumber(String number) {
+        this.number = number;
+    }
+    public String getPhone() {
+        return phone;
+    }
+    public void setPhone(String phone) {
+        this.phone = phone;
+    }
+    public String getStreet() {
+        return street;
+    }
+    public void setStreet(String street) {
+        this.street = street;
+    }
+    
+    public String toString() {
+        return "Address( "+this.street+", "+this.number+" - phone: "+this.phone+" )";
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/Cheese.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/Cheese.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/Cheese.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,134 @@
+package org.drools;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+
+public class Cheese
+    implements
+    CheeseInterface {
+
+    public static String staticString;
+
+    static {
+        staticString = "Cheese is tasty";
+    }
+
+    private String       type;
+    
+    private char         charType;
+
+    private int          price;
+
+    public Cheese() {
+    }
+
+    public Cheese(final String type,
+                  final int price) {
+        this.type = type;
+        this.price = price;
+    }
+
+    public static String getStaticString() {
+        return staticString;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.CheeseInterface#getType()
+     */
+    public String getType() {
+        return this.type;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.CheeseInterface#getPrice()
+     */
+    public int getPrice() {
+        return this.price;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.CheeseInterface#setPrice(int)
+     */
+    public void setPrice(final int price) {
+        this.price = price;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.CheeseInterface#setType(java.lang.String)
+     */
+    public void setType(final String type) {
+        this.type = type;
+    }
+    
+    /**
+     * This is a test method to test shadow proxy delegation
+     * when in the presence of a long or double parameter
+     * @param newPrice
+     * @param bla
+     */
+    public void updatePriceFromLong( long newPrice, double xyz, String bla ) {
+        this.price = (int) newPrice;
+    }
+
+    public String toString() {
+        return "Cheese type='" + this.type + "' price='" + this.price + "'";
+    }
+
+    public int hashCode() {
+        //like org.apache.commons.lang.builder.HashCodeBuilder
+        int hashCode = 17;
+        hashCode = hashCode * 37 + this.price;
+        hashCode = hashCode * 37 + (this.type == null ? 0 : this.type.hashCode());
+        return hashCode;
+    }
+
+    public boolean equals(final Object object) {
+        if ( object == this ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof Cheese) ) {
+            return false;
+        }
+
+        final Cheese other = (Cheese) object;
+
+        return (this.type.equals( other.getType() ) && this.price == other.getPrice());
+    }
+
+    public static int getIndex(final Class clazz,
+                               final String name) throws IntrospectionException {
+        final PropertyDescriptor[] descriptors = Introspector.getBeanInfo( clazz ).getPropertyDescriptors();
+        for ( int i = 0; i < descriptors.length; i++ ) {
+            if ( descriptors[i].getName().equals( name ) ) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    public char getCharType() {
+        return charType;
+    }
+
+    public void setCharType(char charType) {
+        this.charType = charType;
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/CheeseEqual.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/CheeseEqual.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/CheeseEqual.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,91 @@
+package org.drools;
+
+import java.io.Serializable;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class CheeseEqual
+    implements
+    Serializable {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+    protected String          type;
+    protected int             price;
+
+    public CheeseEqual() {
+
+    }
+
+    public CheeseEqual(final String type,
+                       final int price) {
+        super();
+        this.type = type;
+        this.price = price;
+    }
+
+    public int getPrice() {
+        return this.price;
+    }
+
+    public String getType() {
+        return this.type;
+    }
+
+    public void setPrice(final int price) {
+        this.price = price;
+    }
+
+    public String toString() {
+        return "CheeseEqual( type='" + this.type + "', price=" + this.price + " )";
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( (object == null) || (object.getClass() != this.getClass()) ) {
+            return false;
+        }
+
+        final CheeseEqual other = (CheeseEqual) object;
+
+        if ( !this.type.equals( other.type ) ) {
+            return false;
+        }
+
+        if ( this.price != other.price ) {
+            return false;
+        }
+
+        return true;
+    }
+
+    public int hashCode() {
+        //like org.apache.commons.lang.builder.HashCodeBuilder
+        int hashCode = 17;
+        hashCode = hashCode * 37 + this.price;
+        hashCode = hashCode * 37 + (this.type == null ? 0 : this.type.hashCode());
+        return hashCode;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/CheeseInterface.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/CheeseInterface.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/CheeseInterface.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,19 @@
+package org.drools;
+
+public interface CheeseInterface {
+
+    public String getType();
+
+    public int getPrice();
+
+    /**
+     * @param price the price to set
+     */
+    public void setPrice(final int price);
+
+    /**
+     * @param type the type to set
+     */
+    public void setType(final String type);
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/DroolsTestCase.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/DroolsTestCase.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/DroolsTestCase.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,84 @@
+package org.drools;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import junit.framework.TestCase;
+
+public abstract class DroolsTestCase extends TestCase {
+    public DroolsTestCase() {
+        super();
+    }
+
+    public DroolsTestCase(final String name) {
+        super( name );
+    }
+
+    public void assertLength(final int len,
+                             final Object[] array) {
+        assertEquals( Arrays.asList( array ) + " does not have length of " + len,
+                      len,
+                      array.length );
+    }
+
+    public void assertLength(final int len,
+                             final Collection collection) {
+        assertEquals( collection + " does not have length of " + len,
+                      len,
+                      collection.size() );
+    }
+    
+    public void assertNotContains (final Object obj,
+                                   final Object[] array) {
+        try {
+            assertContains( obj, array); 
+            fail( Arrays.asList( array ) + " contains " + obj );    
+        } catch(Throwable t) {
+            // do nothing as this is assertion is ok
+        }
+    }
+
+    public void assertContains(final Object obj,
+                               final Object[] array) {
+        for ( int i = 0; i < array.length; ++i ) {
+            if ( array[i] == obj ) {
+                return;
+            }
+        }
+
+        fail( Arrays.asList( array ) + " does not contain " + obj );
+    }
+
+    public void assertNotContains (final Object obj,
+                                   final Collection collection) {
+        try {
+            assertContains( obj, collection); 
+            fail( collection + " does not contain " + obj );    
+        } catch(Throwable t) {
+            // do nothing as this is assertion is ok
+        }
+    }    
+    
+    public void assertContains(final Object obj,
+                               final Collection collection) {
+        assertTrue( collection + " does not contain " + obj,
+                    collection.contains( obj ) );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/FirstClass.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/FirstClass.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/FirstClass.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,65 @@
+package org.drools;
+
+public class FirstClass {
+	
+	private String item1;
+	private String item2;
+	private String item3;
+	private String item4;
+	private String item5;
+	
+	private String something;
+	
+	public String getItem1() {
+		return item1;
+	}
+	public void setItem1(String item1) {
+		this.item1 = item1;
+	}
+	public String getItem2() {
+		return item2;
+	}
+	public void setItem2(String item2) {
+		this.item2 = item2;
+	}
+	public String getItem3() {
+		return item3;
+	}
+	public void setItem3(String item3) {
+		this.item3 = item3;
+	}
+	public String getItem4() {
+		return item4;
+	}
+	public void setItem4(String item4) {
+		this.item4 = item4;
+	}
+	public String getItem5() {
+		return item5;
+	}
+	public void setItem5(String item5) {
+		this.item5 = item5;
+	}
+	public String getSomething() {
+		return something;
+	}
+	public void setSomething(String something) {
+		this.something = something;
+	}
+	
+	public String toString() {
+		StringBuffer buf = new StringBuffer();
+		buf.append("FirstClass[");
+		buf.append("item1=" + item1 + ", ");
+		buf.append("item2=" + item2 + ", ");
+		buf.append("item3=" + item3 + ", ");
+		buf.append("item4=" + item4 + ", ");
+		buf.append("item5=" + item5 + "]");
+		return buf.toString();
+	}
+	
+	public static class AlternativeKey {
+		
+	}
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/MockFactHandle.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/MockFactHandle.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/MockFactHandle.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,60 @@
+package org.drools;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class MockFactHandle
+    implements
+    FactHandle {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+    private int               id;
+
+    public MockFactHandle(final int id) {
+        this.id = id;
+    }
+
+    public String toExternalForm() {
+        return "[fact:" + this.id + "]";
+    }
+
+    public int hashCode() {
+        return this.id;
+    }
+
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || getClass() != object.getClass() ) {
+            return false;
+        }
+
+        return ((MockFactHandle) object).id == this.id;
+    }
+
+    public long getId() {
+        return this.id;
+    }
+
+    public long getRecency() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/Person.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/Person.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/Person.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,120 @@
+package org.drools;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class Person {
+
+    private String name;
+    private int    age;
+    
+    private String street;
+    private String city;
+    private String state;
+    private String country;
+    
+    private Map addresses;
+    
+    private List addressList;
+    
+    private Address[] addressArray;
+
+    public Person() {
+    }
+    
+    public Person(final String name,
+                  final int age) {
+        this.name = name;
+        this.age = age;
+        this.addresses = new HashMap();
+        this.addressList = new ArrayList();
+        this.addressArray = new Address[10];
+    }
+
+    /**
+     * @return the age
+     */
+    public int getAge() {
+        return this.age;
+    }
+
+    /**
+     * @param age the age to set
+     */
+    public void setAge(final int age) {
+        this.age = age;
+    }
+
+    /**
+     * @return the name
+     */
+    public String getName() {
+        return this.name;
+    }
+
+    /**
+     * @param name the name to set
+     */
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    public String getCity() {
+        return city;
+    }
+
+    public void setCity(String city) {
+        this.city = city;
+    }
+
+    public String getCountry() {
+        return country;
+    }
+
+    public void setCountry(String country) {
+        this.country = country;
+    }
+
+    public String getState() {
+        return state;
+    }
+
+    public void setState(String state) {
+        this.state = state;
+    }
+
+    public String getStreet() {
+        return street;
+    }
+
+    public void setStreet(String street) {
+        this.street = street;
+    }
+
+    public Map getAddresses() {
+        return addresses;
+    }
+
+    public void setAddresses(Map addresses) {
+        this.addresses = addresses;
+    }
+
+    public List getAddressList() {
+        return addressList;
+    }
+
+    public void setAddressList(List addressList) {
+        this.addressList = addressList;
+    }
+
+    public Address[] getAddressArray() {
+        return addressArray;
+    }
+
+    public void setAddressArray(Address[] addressArray) {
+        this.addressArray = addressArray;
+    }
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/RuleBaseConfigurationTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/RuleBaseConfigurationTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/RuleBaseConfigurationTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,141 @@
+package org.drools;
+
+import java.util.Properties;
+
+import org.drools.RuleBaseConfiguration.AssertBehaviour;
+import org.drools.RuleBaseConfiguration.LogicalOverride;
+import org.drools.RuleBaseConfiguration.SequentialAgenda;
+import org.drools.common.ArrayAgendaGroupFactory;
+import org.drools.common.PriorityQueueAgendaGroupFactory;
+
+import junit.framework.TestCase;
+
+public class RuleBaseConfigurationTest extends TestCase {
+
+    public void testSystemProperties() {
+        RuleBaseConfiguration cfg = new RuleBaseConfiguration();
+        assertEquals( AssertBehaviour.IDENTITY,
+                      cfg.getAssertBehaviour() );
+
+        System.setProperty( "drools.assertBehaviour",
+                            "EQUALITY" );
+        cfg = new RuleBaseConfiguration();
+        assertEquals( AssertBehaviour.EQUALITY,
+                      cfg.getAssertBehaviour() );
+        
+        System.getProperties().remove( "drools.assertBehaviour" );        
+    }
+
+    public void testProgrammaticPropertiesFile() {
+        RuleBaseConfiguration cfg = new RuleBaseConfiguration();
+        assertEquals( true,
+                      cfg.isIndexLeftBetaMemory() );
+
+        Properties properties = new Properties();
+        properties.setProperty( "drools.indexLeftBetaMemory",
+                                "false" );
+        cfg = new RuleBaseConfiguration( properties );
+
+        assertEquals( false,
+                      cfg.isIndexLeftBetaMemory() );
+        
+        System.getProperties().remove( "drools.indexLeftBetaMemory" );        
+    }
+    
+    public void testShadowProxy() {
+        // check default for rete
+        RuleBaseConfiguration cfg = new RuleBaseConfiguration();        
+        assertTrue( cfg.isShadowProxy() );
+
+        // check default for sequentail
+        Properties properties = new Properties();
+        properties.setProperty( "drools.sequential", "true" );
+        cfg = new RuleBaseConfiguration(properties);        
+        assertFalse(  cfg.isShadowProxy() );
+        
+        properties = new Properties();
+        properties.setProperty( "drools.shadowproxy", "false" );
+        cfg = new RuleBaseConfiguration(properties);        
+        assertFalse(  cfg.isShadowProxy() );
+        
+        
+        properties = new Properties();
+        properties.setProperty( "drools.sequential", "true" );
+        properties.setProperty( "drools.shadowproxy", "false" );
+        cfg = new RuleBaseConfiguration(properties);        
+        assertFalse(  cfg.isShadowProxy() );         
+    }
+    
+    public void testShadowProxyExcludes() {
+        RuleBaseConfiguration cfg = new RuleBaseConfiguration();
+        
+        Properties properties = new Properties();
+        properties.setProperty( "drools.shadowProxyExcludes", "java.util.List java.util.Map java.lang.reflect.*" );
+        
+        cfg = new RuleBaseConfiguration( properties );
+        
+        assertFalse( cfg.isShadowed( "java.util.List" ) );
+        assertFalse( cfg.isShadowed( "java.util.Map" ) );
+        assertTrue( cfg.isShadowed( "java.util.HashMap" ) );
+        
+        assertFalse( cfg.isShadowed( "java.lang.reflect.Method" ) );
+        
+        assertTrue( cfg.isShadowed( "java.lang.String" ) );
+    }
+    
+    public void testAssertBehaviour() {
+        Properties properties = new Properties();
+        properties.setProperty( "drools.assertBehaviour", "identity" );
+        RuleBaseConfiguration cfg = new RuleBaseConfiguration(properties);
+        
+        assertEquals( AssertBehaviour.IDENTITY, cfg.getAssertBehaviour() );
+        
+        properties = new Properties();
+        properties.setProperty( "drools.assertBehaviour", "equality" );
+        cfg = new RuleBaseConfiguration(properties);
+        
+        assertEquals( AssertBehaviour.EQUALITY, cfg.getAssertBehaviour() );        
+    }
+    
+    public void testLogicalOverride() {
+        Properties properties = new Properties();
+        properties.setProperty( "drools.logicalOverride", "preserve" );
+        RuleBaseConfiguration cfg = new RuleBaseConfiguration(properties);
+        
+        assertEquals( LogicalOverride.PRESERVE, cfg.getLogicalOverride() );
+        
+        properties = new Properties();
+        properties.setProperty( "drools.logicalOverride", "discard" );
+        cfg = new RuleBaseConfiguration(properties);
+        
+        assertEquals( LogicalOverride.DISCARD, cfg.getLogicalOverride() );        
+    }    
+    
+    public void testSequential() {
+        Properties properties = new Properties();
+        properties.setProperty( "drools.sequential", "false" );
+        RuleBaseConfiguration cfg = new RuleBaseConfiguration(properties);
+        
+        assertFalse( cfg.isSequential() );
+        assertTrue( cfg.getAgendaGroupFactory() instanceof PriorityQueueAgendaGroupFactory );
+        
+        properties = new Properties();
+        properties.setProperty( "drools.sequential.agenda", "sequential" );
+        properties.setProperty( "drools.sequential", "true" );
+        cfg = new RuleBaseConfiguration(properties);
+        
+        assertTrue( cfg.isSequential() );
+        assertEquals( SequentialAgenda.SEQUENTIAL, cfg.getSequentialAgenda() );
+        assertTrue( cfg.getAgendaGroupFactory() instanceof ArrayAgendaGroupFactory );
+        
+        properties = new Properties();
+        properties.setProperty( "drools.sequential.agenda", "dynamic" );
+        properties.setProperty( "drools.sequential", "true" );
+        cfg = new RuleBaseConfiguration(properties);
+        
+        assertTrue( cfg.isSequential() );
+        assertEquals( SequentialAgenda.DYNAMIC, cfg.getSequentialAgenda() );
+        assertTrue( cfg.getAgendaGroupFactory() instanceof PriorityQueueAgendaGroupFactory );
+    }    
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/RuleBaseFactoryTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/RuleBaseFactoryTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/RuleBaseFactoryTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,45 @@
+package org.drools;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import junit.framework.TestCase;
+
+import org.drools.common.InternalRuleBase;
+
+public class RuleBaseFactoryTest extends TestCase {
+
+    public void testReteOO() {
+        final RuleBase rb = RuleBaseFactory.newRuleBase();
+        assertTrue( rb instanceof org.drools.reteoo.ReteooRuleBase );
+
+        assertTrue( !"default".equals( ((InternalRuleBase) rb).getId() ) );
+        assertTrue( !"".equals( ((InternalRuleBase) rb).getId() ) );
+        assertNotNull( ((InternalRuleBase) rb).getId() );
+
+        final RuleBase rb2 = RuleBaseFactory.newRuleBase( RuleBase.RETEOO,
+                                                          null );
+
+        assertTrue( rb2 instanceof org.drools.reteoo.ReteooRuleBase );
+        assertNotSame( rb2,
+                       rb );
+
+        assertTrue( !"default".equals( ((InternalRuleBase) rb2).getId() ) );
+        assertTrue( !"".equals( ((InternalRuleBase) rb2).getId() ) );
+        assertNotNull( ((InternalRuleBase) rb2).getId() );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/RuleIntegrationExceptionTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/RuleIntegrationExceptionTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/RuleIntegrationExceptionTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,35 @@
+package org.drools;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import junit.framework.TestCase;
+
+import org.drools.rule.Rule;
+
+public class RuleIntegrationExceptionTest extends TestCase {
+    public void testConstruct() {
+        final Rule rule = new Rule( "cheese" );
+
+        final RuleIntegrationException e = new RuleIntegrationException( rule );
+
+        assertSame( rule,
+                    e.getRule() );
+
+        assertEquals( "cheese cannot be integrated",
+                      e.getMessage() );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/SecondClass.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/SecondClass.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/SecondClass.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,56 @@
+package org.drools;
+
+public class SecondClass {
+	private String item1;
+	private String item2;
+	private String item3;
+	private String item4;
+	private String item5;
+	
+	public String getItem1() {
+		return item1;
+	}
+	public void setItem1(String item1) {
+		this.item1 = item1;
+	}
+	public String getItem2() {
+		return item2;
+	}
+	public void setItem2(String item2) {
+		this.item2 = item2;
+	}
+	public String getItem3() {
+		return item3;
+	}
+	public void setItem3(String item3) {
+		this.item3 = item3;
+	}
+	public String getItem4() {
+		return item4;
+	}
+	public void setItem4(String item4) {
+		this.item4 = item4;
+	}
+	public String getItem5() {
+		return item5;
+	}
+	public void setItem5(String item5) {
+		this.item5 = item5;
+	}
+	
+	public String toString() {
+		StringBuffer buf = new StringBuffer();
+		buf.append("SecondClass[");
+		buf.append("item1=" + item1 + ", ");
+		buf.append("item2=" + item2 + ", ");
+		buf.append("item3=" + item3 + ", ");
+		buf.append("item4=" + item4 + ", ");
+		buf.append("item5=" + item5 + "]");
+		return buf.toString();
+	}
+	
+	public static class AlternativeKey {
+		
+	}
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/TestWorkingMemoryEventListener.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/TestWorkingMemoryEventListener.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/TestWorkingMemoryEventListener.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,76 @@
+package org.drools;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.drools.event.ActivationCancelledEvent;
+import org.drools.event.ActivationCreatedEvent;
+import org.drools.event.AfterActivationFiredEvent;
+import org.drools.event.ObjectInsertedEvent;
+import org.drools.event.ObjectUpdatedEvent;
+import org.drools.event.ObjectRetractedEvent;
+import org.drools.event.WorkingMemoryEventListener;
+
+public class TestWorkingMemoryEventListener
+    implements
+    WorkingMemoryEventListener,
+    Serializable {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+    public int                asserted;
+    public int                modified;
+    public int                retracted;
+    public int                tested;
+    public int                created;
+    public int                cancelled;
+    public int                fired;
+
+    public TestWorkingMemoryEventListener() {
+        // intentionally left blank
+    }
+
+    public void objectInserted(final ObjectInsertedEvent event) {
+        this.asserted++;
+    }
+
+    public void objectUpdated(final ObjectUpdatedEvent event) {
+        this.modified++;
+    }
+
+    public void objectRetracted(final ObjectRetractedEvent event) {
+        this.retracted++;
+    }
+
+    /*
+     * public void conditionTested(ConditionTestedEvent event) { tested++; }
+     */
+    public void activationCreated(final ActivationCreatedEvent event) {
+        this.created++;
+    }
+
+    public void activationCancelled(final ActivationCancelledEvent event) {
+        this.cancelled++;
+    }
+
+    public void activationFired(final AfterActivationFiredEvent event) {
+        this.fired++;
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/DirectoryScannerTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/DirectoryScannerTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/DirectoryScannerTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,51 @@
+package org.drools.agent;
+
+import java.io.File;
+import java.util.Properties;
+
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.rule.Package;
+
+import junit.framework.TestCase;
+
+
+
+public class DirectoryScannerTest extends TestCase {
+
+    public void testScan() throws Exception {
+        File dir = RuleBaseAssemblerTest.getTempDirectory();
+        
+        Package p1 = new Package("p1");
+        Package p2 = new Package("p2");
+        File p1f = new File(dir, "p1.pkg");
+        File p2f = new File(dir, "p2.pkg");
+        
+        RuleBaseAssemblerTest.writePackage( p1, p1f );
+        RuleBaseAssemblerTest.writePackage( p2, p2f);
+        
+        DirectoryScanner scan = new DirectoryScanner();
+        scan.listener = new MockListener();
+        Properties props = new Properties();
+        props.setProperty( RuleAgent.DIRECTORY, dir.getPath() );
+                
+        scan.configure( props );
+        
+        RuleBase rb = RuleBaseFactory.newRuleBase();
+        PackageProvider.applyChanges( rb, true, scan.loadPackageChanges(), new MockListener() );
+
+        assertEquals(2, rb.getPackages().length);
+                
+        Package p3 = new Package("p3");
+        File p3f = new File(dir, "p3.pkg");
+        
+        RuleBaseAssemblerTest.writePackage( p3, p3f );
+        
+        PackageProvider.applyChanges( rb, true, scan.loadPackageChanges(), new MockListener() );
+
+        assertEquals(3, rb.getPackages().length);        
+    }
+    
+    
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/FileScannerTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/FileScannerTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/FileScannerTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,103 @@
+package org.drools.agent;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.ObjectOutputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.rule.Package;
+
+import junit.framework.TestCase;
+
+public class FileScannerTest extends TestCase {
+
+    public void testHasChanged() {
+        Map lastMod = new HashMap();
+        
+        FileScanner scan = new FileScanner();
+        assertTrue(scan.hasChanged( "/goo/ber", lastMod, 42 ));
+
+        assertFalse(scan.hasChanged( "/goo/ber", lastMod, 42 ));
+        assertTrue(scan.hasChanged( "/goo/baaaa", lastMod, 42 ));
+
+        assertFalse(scan.hasChanged( "/goo/baaaa", lastMod, 42 ));
+        assertFalse(scan.hasChanged( "/goo/ber", lastMod, 42 ));
+
+        
+        assertTrue(scan.hasChanged( "/goo/ber", lastMod, 400 ));
+        assertFalse(scan.hasChanged( "/goo/baaaa", lastMod, 42 ));
+        assertTrue(scan.hasChanged( "/goo/baaaa", lastMod, 69 ));
+    }
+    
+    public void testScanAndLoad() throws Exception {
+        Package p1 = new Package("p1");
+        Package p2 = new Package("p2");
+        
+        File dir = RuleBaseAssemblerTest.getTempDirectory();
+        File p1f = new File(dir, "p1.pkg");
+        File p2f = new File(dir, "p2.pkg");
+        
+        RuleBaseAssemblerTest.writePackage( p1, p1f );
+        RuleBaseAssemblerTest.writePackage( p2, p2f);
+        
+        FileScanner scan = new FileScanner();
+        Properties props = new Properties();
+        props.setProperty( RuleAgent.FILES, p1f.getPath() + " " + p2f.getPath() );
+        scan.configure( props );
+        
+        RuleBase rb = RuleBaseFactory.newRuleBase();
+        PackageProvider.applyChanges( rb, true, scan.loadPackageChanges(), new MockListener() );
+        
+        
+        
+        assertEquals(2, rb.getPackages().length);
+        assertTrue("p1".equals(rb.getPackages()[0].getName()) || "p1".equals(rb.getPackages()[1].getName()));
+        assertTrue("p2".equals(rb.getPackages()[0].getName()) || "p2".equals(rb.getPackages()[1].getName()));
+
+        PackageProvider.applyChanges( rb, true, scan.loadPackageChanges(), new MockListener() );
+        assertEquals(2, rb.getPackages().length);
+        assertTrue("p1".equals(rb.getPackages()[0].getName()) || "p1".equals(rb.getPackages()[1].getName()));
+        assertTrue("p2".equals(rb.getPackages()[0].getName()) || "p2".equals(rb.getPackages()[1].getName()));
+
+        RuleBaseAssemblerTest.writePackage( p2, p2f );
+        PackageProvider.applyChanges( rb, true, scan.loadPackageChanges(), new MockListener() );
+
+
+        assertEquals(2, rb.getPackages().length);
+        assertTrue("p1".equals(rb.getPackages()[0].getName()) || "p1".equals(rb.getPackages()[1].getName()));
+        assertTrue("p2".equals(rb.getPackages()[0].getName()) || "p2".equals(rb.getPackages()[1].getName()));
+        
+    }
+    
+    public void testEmptyList() throws Exception {
+        FileScanner scan = new FileScanner();
+        RuleBase rb = RuleBaseFactory.newRuleBase();
+        
+        PackageProvider.applyChanges( rb, true, scan.loadPackageChanges(), new MockListener() );
+
+        assertEquals(0, rb.getPackages().length);
+    }
+    
+    public void testFileChanges() throws Exception {
+        File dir = RuleBaseAssemblerTest.getTempDirectory();
+        File t = new File(dir, "x.bar");
+        
+        Package x = new Package("x");
+        RuleBaseAssemblerTest.writePackage( x, t );
+        
+        FileScanner scan = new FileScanner();
+        Map updates = new HashMap();
+        assertTrue(scan.hasChanged( "x", updates, t.lastModified() ));
+        assertFalse(scan.hasChanged( "x", updates, t.lastModified() ));
+        
+    }
+
+    
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/MockListener.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/MockListener.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/MockListener.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,32 @@
+package org.drools.agent;
+
+public class MockListener
+    implements
+    AgentEventListener {
+
+    public void debug(String message) {
+        
+
+    }
+
+    public void exception(Exception e) {
+        
+
+    }
+
+    public void info(String message) {
+        
+
+    }
+
+    public void setAgentName(String name) {
+        
+
+    }
+
+    public void warning(String message) {
+        
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/MockProvider.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/MockProvider.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/MockProvider.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,20 @@
+package org.drools.agent;
+
+import java.util.Properties;
+
+import org.drools.rule.Package;
+public  class MockProvider extends PackageProvider {
+
+        public MockProvider() {
+        }
+        
+        public void configure(Properties config) {
+        }
+
+        Package[] loadPackageChanges() {
+            return null;
+        }
+
+
+        
+    }
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/MockRuleAgent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/MockRuleAgent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/MockRuleAgent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,23 @@
+package org.drools.agent;
+
+import java.util.Properties;
+
+import org.drools.RuleBaseConfiguration;
+
+public class MockRuleAgent extends RuleAgent {
+
+    
+    public boolean refreshCalled = false;
+    
+    public MockRuleAgent() {
+        super( new RuleBaseConfiguration() );
+    }
+
+    public void refreshRuleBase() {
+        refreshCalled = true;
+        
+    }
+
+    
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/RuleAgentTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/RuleAgentTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/RuleAgentTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,467 @@
+package org.drools.agent;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Random;
+
+import org.drools.RuleBase;
+import org.drools.RuleBaseConfiguration;
+import org.drools.common.InternalRuleBase;
+import org.drools.rule.Package;
+
+import junit.framework.TestCase;
+
+public class RuleAgentTest extends TestCase {
+
+    public void testLists() {
+        String s = "\tfoo.bar\n baz.bar\t whee ";
+        List result = RuleAgent.list( s );
+        assertEquals(3, result.size());
+        assertEquals("foo.bar", result.get( 0 ));
+        assertEquals("baz.bar", result.get(1));
+        assertEquals("whee", result.get(2));
+
+        s = null;
+        result = RuleAgent.list( s );
+        assertNotNull(result);
+        assertEquals(0, result.size());
+
+        s = "\"yeah man\" \"another one\"";
+        result = RuleAgent.list( s );
+        assertEquals(2, result.size());
+        assertEquals("yeah man", result.get( 0 ));
+        assertEquals("another one", result.get(1));
+
+        s = "\"yeah man\"";
+        result = RuleAgent.list( s );
+        assertEquals(1, result.size());
+        assertEquals("yeah man", result.get( 0 ));
+
+        s = "YEAH";
+        result = RuleAgent.list( s );
+        assertEquals(1, result.size());
+        assertEquals("YEAH", result.get( 0 ));
+
+    }
+
+    public void testFiles() throws Exception {
+        File dir = RuleBaseAssemblerTest.getTempDirectory();
+
+        Package p1 = new Package("p1");
+        File p1f = new File(dir, "p1.pkg");
+        RuleBaseAssemblerTest.writePackage( p1, p1f );
+
+        Package p2 = new Package("p2");
+        File p2f = new File(dir, "p2.pkg");
+        RuleBaseAssemblerTest.writePackage( p2, p2f );
+
+        String path = dir.getPath() + "/" + "p1.pkg " + dir.getPath() + "/" + "p2.pkg";
+
+        Properties props = new Properties();
+        props.setProperty( "file", path );
+        RuleAgent ag = RuleAgent.newRuleAgent(props);
+        RuleBase rb = ag.getRuleBase();
+        assertNotNull(rb);
+        assertEquals(2, rb.getPackages().length);
+
+        assertFalse(ag.isPolling());
+
+        props.setProperty( "poll", "1" );
+        ag = RuleAgent.newRuleAgent(props);
+        assertTrue(ag.isPolling());
+
+        ag.stopPolling();
+        assertFalse(ag.isPolling());
+
+    }
+
+//    public void testSpaces() throws Exception {
+//        File dir = RuleBaseAssemblerTest.getTempDirectory();
+//        File dir_ = new File(dir, "whee waah");
+//        dir_.mkdir();
+//        System.err.println(dir_.getPath());
+//
+//
+//        File x = new File("/tmp/__temp_test_drools_packages/whee waah");
+//        assertTrue(x.exists());
+//    }
+
+    public void testPollingFilesRuleBaseUpdate() throws Exception {
+        //RuleBaseAssemblerTest.clearTempDirectory();
+        final File dir = RuleBaseAssemblerTest.getTempDirectory();
+
+        Random rnd = new Random(System.currentTimeMillis());
+
+        final Package p1 = new Package("p1");
+        final File p1f = new File(dir, rnd.nextLong() + ".pkg");
+        RuleBaseAssemblerTest.writePackage( p1, p1f );
+
+        String path = p1f.getPath();
+
+        Properties props = new Properties();
+        props.setProperty( "file", path );
+
+        RuleAgent ag = RuleAgent.newRuleAgent(props);
+
+
+        RuleBase rb = ag.getRuleBase();
+        assertEquals(1, rb.getPackages().length);
+        assertEquals(0, rb.getPackages()[0].getGlobals().size());
+
+        p1.addGlobal( "goo", String.class );
+
+        Thread.sleep( 1000 );
+
+        RuleBaseAssemblerTest.writePackage( p1, p1f );
+
+        RuleBase rb_ = ag.getRuleBase();
+        assertSame(rb, rb_);
+        assertEquals(1, rb.getPackages().length);
+        assertEquals(0, rb.getPackages()[0].getGlobals().size());
+
+        Thread.sleep( 1000 );
+
+        ag.refreshRuleBase();
+
+        RuleBase rb2 = ag.getRuleBase();
+        assertSame(rb, rb2);
+
+        assertEquals(1, rb2.getPackages().length);
+        assertEquals(1, rb2.getPackages()[0].getGlobals().size());
+
+        //now check subsequent changes
+        p1.addGlobal( "goo2", String.class );
+        System.err.println("-->WRITING CHANGE");
+        Thread.sleep( 1000 );
+        RuleBaseAssemblerTest.writePackage( p1, p1f );
+        System.err.println("-->WROTE CHANGE");
+        Thread.sleep( 1000 );
+        ag.refreshRuleBase();
+
+        RuleBase rb2_ = ag.getRuleBase();
+        assertSame(rb2_, rb2);
+        assertEquals(1, rb2_.getPackages().length);
+        assertEquals(2, rb2_.getPackages()[0].getGlobals().size());
+
+        ag.refreshRuleBase();
+
+        RuleBase rb3 = ag.getRuleBase();
+        assertSame(rb3, rb2);
+
+        assertEquals(1, rb3.getPackages().length);
+        assertEquals(2, rb3.getPackages()[0].getGlobals().size());
+
+        ag.refreshRuleBase();
+        ag.refreshRuleBase();
+
+        assertEquals(1, rb3.getPackages().length);
+        assertEquals(2, rb3.getPackages()[0].getGlobals().size());
+
+
+    }
+
+    public void testPollingFilesRuleBaseReplace() throws Exception {
+        File dir = RuleBaseAssemblerTest.getTempDirectory();
+
+        Package p1 = new Package("p1");
+        File p1f = new File(dir, "p43_.pkg");
+        RuleBaseAssemblerTest.writePackage( p1, p1f );
+
+        Package p2 = new Package("p2");
+        File p2f = new File(dir, "p44_.pkg");
+        RuleBaseAssemblerTest.writePackage( p2, p2f );
+
+
+
+        String path = dir.getPath() + "/" + "p43_.pkg " + dir.getPath() + "/p44_.pkg";
+
+        Properties props = new Properties();
+        props.setProperty( "file", path );
+
+        props.setProperty( "newInstance", "true" );
+        RuleAgent ag = RuleAgent.newRuleAgent(props);
+
+        assertTrue(ag.isNewInstance());
+
+        RuleBase rb = ag.getRuleBase();
+        assertEquals(2, rb.getPackages().length);
+
+        RuleBase rb_ = ag.getRuleBase();
+        assertSame(rb, rb_);
+
+
+        ag.refreshRuleBase();
+
+        assertSame(rb, ag.getRuleBase());
+        Thread.sleep( 1000 );
+        //only change one
+        RuleBaseAssemblerTest.writePackage( p1, p1f );
+        Thread.sleep( 1000 );
+        ag.refreshRuleBase();
+
+
+        rb_ = ag.getRuleBase();
+
+        assertNotSame( rb, rb_ );
+
+
+        //check we will have 2
+        assertEquals(2, rb_.getPackages().length);
+
+        ag.refreshRuleBase();
+        ag.refreshRuleBase();
+
+        RuleBase rb__ = ag.getRuleBase();
+        assertSame(rb_, rb__);
+
+
+
+
+    }
+
+
+    public void testDirectory() throws Exception {
+        File dir = RuleBaseAssemblerTest.getTempDirectory();
+
+        Package p1 = new Package("p1");
+        File p1f = new File(dir, "p43_.pkg");
+
+        File junk = new File(dir, "xxx.poo");
+        FileOutputStream ojunk = new FileOutputStream(junk);
+        ojunk.write("ignore me".getBytes());
+        ojunk.flush();
+        ojunk.close();
+
+        RuleBaseAssemblerTest.writePackage( p1, p1f );
+
+        Properties props = new Properties();
+        props.setProperty( RuleAgent.DIRECTORY, dir.getPath() );
+        props.setProperty( RuleAgent.CONFIG_NAME, "goo" );
+
+
+        RuleAgent ag = RuleAgent.newRuleAgent(props);
+
+        ag.refreshRuleBase();
+
+        RuleBase rb = ag.getRuleBase();
+        assertNotNull(rb);
+        assertEquals(1, rb.getPackages().length);
+    }
+
+    public void testCustomRuleBaseConfiguration() throws Exception {
+        final File dir = RuleBaseAssemblerTest.getTempDirectory();
+
+        Random rnd = new Random(System.currentTimeMillis());
+
+        final Package p1 = new Package("p1");
+        final File p1f = new File(dir, rnd.nextLong() + ".pkg");
+        RuleBaseAssemblerTest.writePackage( p1, p1f );
+
+        String path = p1f.getPath();
+
+        Properties props = new Properties();
+        props.setProperty( "file", path );
+
+        // Check a default value for the RuleBase's RuleBaseConfiguration
+        RuleAgent agent = RuleAgent.newRuleAgent( props );
+        RuleBaseConfiguration conf = ((InternalRuleBase) agent.getRuleBase()).getConfiguration();
+        assertEquals( false, conf.isSequential() );
+
+        // Pass in a RuleBaseConfiguration and make sure the RuleBase was created with it
+        conf = new RuleBaseConfiguration();
+        conf.setSequential( true );
+        agent = RuleAgent.newRuleAgent( props, conf );
+        conf = ((InternalRuleBase) agent.getRuleBase()).getConfiguration();
+        assertEquals( true, conf.isSequential() );
+    }
+
+    public void testLoadSampleConfig() {
+        RuleAgent ag = new RuleAgent( new RuleBaseConfiguration()  );
+        Properties props = ag.loadFromProperties( "/sample-agent-config.properties" );
+        assertEquals("10", props.getProperty( RuleAgent.POLL_INTERVAL ));
+        assertEquals("/home/packages", props.getProperty( RuleAgent.DIRECTORY ));
+        assertEquals("true", props.getProperty( RuleAgent.NEW_INSTANCE ));
+        assertEqualsIgnoreWhitespace( "/foo/bar.pkg /wee/waa.pkg /wee/waa2.pkg", props.getProperty( RuleAgent.FILES ));
+    }
+
+    private void assertEqualsIgnoreWhitespace(final String expected,
+                                              final String actual) {
+        final String cleanExpected = expected.replaceAll( "\\s+",
+                                                          "" );
+        final String cleanActual = actual.replaceAll( "\\s+",
+                                                      "" );
+
+        assertEquals( cleanExpected,
+                      cleanActual );
+    }
+
+    public void testEventListenerSetup() throws Exception {
+        RuleAgent ag = new RuleAgent( new RuleBaseConfiguration() );
+        assertNotNull(ag.listener);
+
+        final String[] name = new String[1];
+
+        AgentEventListener list = new AgentEventListener() {
+            public void debug(String message) {
+            }
+            public void exception(Exception e) {
+            }
+            public void info(String message) {
+            }
+            public void warning(String message) {
+            }
+            public void setAgentName(String n) {
+                name[0] = n;
+            }
+        };
+
+        File dir = RuleBaseAssemblerTest.getTempDirectory();
+
+        Package p1 = new Package("p1");
+        File p1f = new File(dir, "p42_.pkg");
+        RuleBaseAssemblerTest.writePackage( p1, p1f );
+
+        String path = dir.getPath() + "/" + "p42_.pkg";
+
+        Properties props = new Properties();
+        props.setProperty( "file", path );
+        props.setProperty( "poll", "1" );
+        props.setProperty( "name", "poo" );
+        ag = RuleAgent.newRuleAgent(props, list);
+
+        assertEquals(list, ag.listener);
+        assertEquals("poo", name[0]);
+        ag.stopPolling();
+    }
+
+
+    public void testPollSetup() throws Exception {
+        //this is the only method that will actually run the polling timer
+
+
+        Properties props = new Properties();
+        //props.setProperty( "file", "/foo/bar" );
+        props.setProperty( "poll", "1" );
+        MockRuleAgent ag = new MockRuleAgent();
+        ag.init(props);
+
+        assertTrue(ag.isPolling());
+        assertTrue(ag.refreshCalled);
+        ag.refreshCalled = false;
+        assertFalse(ag.refreshCalled);
+        Thread.sleep( 100 );
+        assertFalse(ag.refreshCalled);
+        Thread.sleep( 1500 );
+        assertTrue(ag.refreshCalled);
+        ag.refreshCalled = false;
+        Thread.sleep( 100 );
+        assertFalse(ag.refreshCalled);
+        Thread.sleep( 1500 );
+        assertTrue(ag.refreshCalled);
+        ag.stopPolling();
+
+    }
+
+    public void testProviderMap() throws Exception {
+
+        assertEquals(3, RuleAgent.PACKAGE_PROVIDERS.size());
+        assertTrue(RuleAgent.PACKAGE_PROVIDERS.containsKey( "url" ));
+        assertTrue(RuleAgent.PACKAGE_PROVIDERS.containsKey( "file" ));
+        assertTrue(RuleAgent.PACKAGE_PROVIDERS.containsKey( "dir" ));
+        assertFalse(RuleAgent.PACKAGE_PROVIDERS.containsKey( "XXX" ));
+        assertTrue(RuleAgent.PACKAGE_PROVIDERS.get( "url" ).equals( URLScanner.class ));
+
+    }
+
+    public void testLoadUpFromProperties() throws Exception {
+        AnotherRuleAgentMock ag = new AnotherRuleAgentMock();
+        Map oldMap = ag.PACKAGE_PROVIDERS;
+
+        ag.PACKAGE_PROVIDERS = new HashMap();
+        ag.PACKAGE_PROVIDERS.put( RuleAgent.URLS, MockProvider.class );
+        ag.PACKAGE_PROVIDERS.put( RuleAgent.FILES, MockProvider.class );
+        ag.PACKAGE_PROVIDERS.put( RuleAgent.DIRECTORY, MockProvider.class );
+
+
+        Properties props = new Properties();
+        props.load( this.getClass().getResourceAsStream( "/rule-agent-config.properties" ) );
+        MockEventListener evl = new MockEventListener();
+        ag.listener = evl;
+
+        ag.init( props );
+
+
+        assertTrue(ag.newInstance);
+        assertEquals(3, ag.provs.size());
+        assertEquals(30, ag.secondsToRefresh);
+        assertEquals("MyConfig", evl.name);
+        assertFalse(evl.exceptionCalled);
+        assertFalse(evl.warningCalled);
+        assertTrue(evl.infoCalled);
+
+        ag.PACKAGE_PROVIDERS = oldMap;
+    }
+
+
+
+
+    class AnotherRuleAgentMock extends RuleAgent {
+
+        public int secondsToRefresh;
+        public List provs;
+        public boolean newInstance;
+
+        public AnotherRuleAgentMock() {
+            super( new RuleBaseConfiguration() );
+        }
+
+        synchronized void configure(boolean newInstance, List provs, int secondsToRefresh) {
+            this.newInstance = newInstance;
+            this.provs = provs;
+            this.secondsToRefresh = secondsToRefresh;
+        }
+
+
+
+    }
+
+
+    class MockEventListener implements AgentEventListener {
+
+
+        public String name;
+        boolean exceptionCalled = false;
+        boolean infoCalled = false;
+        boolean warningCalled;
+
+        public void debug(String message) {
+
+
+        }
+
+        public void exception(Exception e) {
+            this.exceptionCalled = true;
+        }
+
+        public void info(String message) {
+            if (message != null) this.infoCalled = true;
+        }
+
+        public void setAgentName(String name) {
+            this.name = name;
+        }
+
+        public void warning(String message) {
+            this.warningCalled = false;
+
+        }
+
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/RuleBaseAssemblerTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/RuleBaseAssemblerTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/RuleBaseAssemblerTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,99 @@
+package org.drools.agent;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.common.DroolsObjectInputStream;
+import org.drools.rule.Package;
+
+import junit.framework.TestCase;
+
+public class RuleBaseAssemblerTest extends TestCase {
+
+    
+    public void testAssemblePackages() throws Exception {
+        RuleBase rb = RuleBaseFactory.newRuleBase();
+        rb.addPackage( new Package("goober") );
+        
+        Package p1 = new Package("p1");
+        
+        File f = getTempDirectory();
+        
+        File p1file = new File(f, "p1.pkg");
+        
+        writePackage( p1, p1file );
+        
+        Package p1_ = readPackage( p1file );
+        
+        rb = RuleBaseFactory.newRuleBase();
+        rb.addPackage( p1_ );
+        
+        
+    }
+
+    public static Package readPackage(File p1file) throws IOException,
+                                            FileNotFoundException,
+                                            ClassNotFoundException {
+        ObjectInputStream in = new DroolsObjectInputStream(new FileInputStream(p1file));
+        Package p1_ = (Package) in.readObject();
+        in.close();
+        return p1_;
+    }
+
+    public static void writePackage(Package pkg, File p1file) throws IOException,
+                                                      FileNotFoundException {
+        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(p1file));
+        out.writeObject( pkg );
+        out.flush(); out.close();
+    }
+
+    public static File getTempDirectory() {
+        File f = tempDir();
+        if (f.exists()) {
+            if (f.isFile()) {
+                throw new IllegalStateException("The temp directory exists as a file. Nuke it now !");
+            }
+            deleteDir( f );
+            f.mkdir();
+        } else {
+            f.mkdir();
+        }
+        return f;
+    }
+
+    private static File tempDir() {
+        File tmp = new File(System.getProperty( "java.io.tmpdir" ));
+        
+        return new File(tmp, "__temp_test_drools_packages");
+    }
+    
+    public static boolean deleteDir(File dir) {
+        
+        if (dir.isDirectory()) {
+            String[] children = dir.list();
+            for (int i=0; i<children.length; i++) {
+                boolean success = deleteDir(new File(dir, children[i]));
+                if (!success) {
+                    //throw new RuntimeException("Unable to delete !");
+                    return false;
+                }
+            }
+        }
+    
+        // The directory is now empty so delete it
+        return dir.delete();
+    }
+
+    public static void clearTempDirectory() {
+        deleteDir( tempDir() );
+        
+    }      
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/URLScannerTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/URLScannerTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/agent/URLScannerTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,314 @@
+package org.drools.agent;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.common.DroolsObjectInputStream;
+import org.drools.rule.Package;
+
+public class URLScannerTest extends TestCase {
+
+    public void testFileURLCache() throws Exception {
+        File dir = RuleBaseAssemblerTest.getTempDirectory();
+
+        String url = "http://localhost:8080/foo/bar.bar/packages/IMINYRURL/LATEST";
+        String fileName = URLEncoder.encode( url, "UTF-8" );
+
+        File f = new File( dir,
+                           fileName );
+
+        Package p = new Package( "x" );
+
+        RuleBaseAssemblerTest.writePackage( p, f );
+
+        DroolsObjectInputStream in = new DroolsObjectInputStream( new FileInputStream( f ) );
+        Package p_ = (Package) in.readObject();
+        assertEquals( "x", p_.getName() );
+
+    }
+
+    //    public void testGetURL() throws Exception {
+    //        String url = "http://localhost:8080/foo/bar.bar/packages/IMINYRURL/LATEST";
+    //        URL u = new URL(url);
+    //        assertEquals(url, URLScanner.getURL( u ));
+    //        //URLConnection con = u.openConnection();
+    //        //con.connect();
+    //    }
+
+    public void testGetFiles() throws Exception {
+
+        URL u1 = new URL( "http://localhost:8080/foo/bar.bar/packages/IMINYRURL/LATEST" );
+        URL u2 = new URL( "http://localhost:8080/foo/bar.bar/packages/IMINYRURL/PROD" );
+        URLScanner scan = new URLScanner();
+
+        File dir = RuleBaseAssemblerTest.getTempDirectory();
+        File[] result = scan.getFiles( new URL[]{u1, u2}, dir );
+
+        assertEquals( 2, result.length );
+        assertEquals( dir.getPath(), result[0].getParent() );
+
+        File f1 = result[0];
+        File f2 = result[1];
+        assertEquals( "http%3A%2F%2Flocalhost%3A8080%2Ffoo%2Fbar.bar%2Fpackages%2FIMINYRURL%2FLATEST.pkg", f1.getName() );
+        assertEquals( "http%3A%2F%2Flocalhost%3A8080%2Ffoo%2Fbar.bar%2Fpackages%2FIMINYRURL%2FPROD.pkg", f2.getName() );
+
+    }
+
+    public void testConfig() throws Exception {
+        URLScanner scan = new URLScanner();
+
+        File dir = RuleBaseAssemblerTest.getTempDirectory();
+
+        Properties config = new Properties();
+        config.setProperty( RuleAgent.LOCAL_URL_CACHE, dir.getPath() );
+        config.setProperty( RuleAgent.URLS, "http://goo.ber http://wee.waa" );
+
+        scan.configure( config );
+
+        assertNotNull( scan.lastUpdated );
+        assertEquals( 2, scan.urls.length );
+        assertEquals( "http://goo.ber", scan.urls[0].toExternalForm() );
+        assertEquals( "http://wee.waa", scan.urls[1].toExternalForm() );
+        assertNotNull( scan.localCacheFileScanner );
+
+        assertEquals( 2, scan.localCacheFileScanner.files.length );
+
+        assertEquals( "http%3A%2F%2Fgoo.ber.pkg", scan.localCacheFileScanner.files[0].getName() );
+        assertEquals( "http%3A%2F%2Fwee.waa.pkg", scan.localCacheFileScanner.files[1].getName() );
+
+    }
+
+    public void testLastUpdatedError() {
+        LastUpdatedPing ping = new LastUpdatedPing();
+        assertTrue( ping.isError() );
+        ping.responseMessage = "ABC";
+        ping.lastUpdated = 42;
+        assertTrue( ping.isError() );
+        ping.responseMessage = "200 OK";
+        assertFalse( ping.isError() );
+    }
+
+    public void testUpdateNoLocalCache() throws Exception {
+        URLScanner scan = new URLScanner();
+        File dir = RuleBaseAssemblerTest.getTempDirectory();
+
+        int numfiles = dir.list().length;
+
+
+        Properties config = new Properties();
+        //config.setProperty( RuleAgent.LOCAL_URL_CACHE, dir.getPath() );
+        config.setProperty( RuleAgent.URLS, "http://goo2.ber http://wee2.waa" );
+
+        scan.configure( config );
+
+        scan.httpClient = new IHttpClient() {
+
+            public LastUpdatedPing checkLastUpdated(URL url) throws IOException {
+                LastUpdatedPing ping = new LastUpdatedPing();
+                ping.lastUpdated = 123;
+                ping.responseMessage = "200 OK";
+                return ping;
+            }
+
+            public Package fetchPackage(URL url) throws IOException {
+                if ( url.toExternalForm().equals( "http://goo2.ber" ) ) {
+                    return new Package( "goo2.ber" );
+                } else {
+                    return new Package( "wee2.waa" );
+                }
+            }
+
+        };
+
+        assertNull( scan.localCacheFileScanner );
+        assertNull( scan.localCacheDir );
+
+        RuleBase rb = RuleBaseFactory.newRuleBase();
+        AgentEventListener list = getNilListener();
+        PackageProvider.applyChanges( rb, false, scan.loadPackageChanges(), list );
+
+
+        assertEquals( 2, rb.getPackages().length );
+
+        assertExists(new String[] {"goo2.ber", "wee2.waa"}, rb.getPackages());
+
+
+
+        assertEquals( numfiles, dir.list().length );
+    }
+
+
+
+    private AgentEventListener getNilListener() {
+        return new MockListener();
+    }
+
+    private void assertExists(String[] names, Package[] packages) {
+        for ( int i = 0; i < packages.length; i++ ) {
+            String name = packages[i].getName();
+            int matches = 0;
+            for ( int j = 0; j < names.length; j++ ) {
+                if (name.equals( names[j] )) {
+                    matches++;
+                }
+            }
+            assertEquals("Should only have one package named " + name, 1, matches);
+        }
+
+    }
+
+    public void testUpdateWithLocalCache() {
+        URLScanner scan = new URLScanner();
+        scan.listener = new MockListener();
+        File dir = RuleBaseAssemblerTest.getTempDirectory();
+
+        Properties config = new Properties();
+        config.setProperty( RuleAgent.LOCAL_URL_CACHE, dir.getPath() );
+        config.setProperty( RuleAgent.URLS, "http://goo.ber http://wee.waa" );
+
+        scan.configure( config );
+
+        scan.httpClient = new IHttpClient() {
+
+            public LastUpdatedPing checkLastUpdated(URL url) throws IOException {
+                LastUpdatedPing ping = new LastUpdatedPing();
+                ping.lastUpdated = 123;
+                ping.responseMessage = "200 OK";
+                return ping;
+            }
+
+            public Package fetchPackage(URL url) throws IOException {
+                if ( url.toExternalForm().equals( "http://goo.ber" ) ) {
+                    return new Package( "goo.ber" );
+                } else {
+                    return new Package( "wee.waa" );
+                }
+            }
+
+        };
+
+        assertNotNull( scan.localCacheFileScanner );
+        assertNotNull( scan.localCacheDir );
+
+        RuleBase rb = RuleBaseFactory.newRuleBase();
+        PackageProvider.applyChanges( rb, false, scan.loadPackageChanges(), getNilListener() );
+
+
+        assertEquals( 2, rb.getPackages().length );
+        assertTrue("goo.ber".equals(rb.getPackages()[0].getName()) || "goo.ber".equals(rb.getPackages()[1].getName()));
+        assertTrue("wee.waa".equals(rb.getPackages()[0].getName()) || "wee.waa".equals(rb.getPackages()[1].getName()));
+
+        //assertEquals( 2, dir.list().length );
+
+        //now check with failures:
+        scan.httpClient = new IHttpClient() {
+
+            public LastUpdatedPing checkLastUpdated(URL url) throws IOException {
+                LastUpdatedPing ping = new LastUpdatedPing();
+
+                if (url.toExternalForm().equals( "http://wee.waa" )) {
+                    ping.lastUpdated = -1;
+                    ping.responseMessage = "XXX";
+
+                } else {
+                    ping.lastUpdated = 123;
+                    ping.responseMessage = "200 OK";
+                }
+                return ping;
+            }
+
+            public Package fetchPackage(URL url) throws IOException {
+                throw new IOException("poo");
+            }
+
+        };
+
+        rb = RuleBaseFactory.newRuleBase();
+        assertEquals(0, rb.getPackages().length);
+        PackageProvider.applyChanges( rb, true, scan.loadPackageChanges(), getNilListener() );
+
+        assertEquals(2, rb.getPackages().length);
+
+        final boolean[] fetchCalled = new boolean[1];
+
+        fetchCalled[0] = false;
+
+        //now check with IOExceptions
+        scan.httpClient = new IHttpClient() {
+
+            public LastUpdatedPing checkLastUpdated(URL url) throws IOException {
+                LastUpdatedPing ping = new LastUpdatedPing();
+                ping.lastUpdated = 1234;
+                ping.responseMessage = "200 OK";
+                return ping;
+            }
+
+            public Package fetchPackage(URL url) throws IOException {
+                fetchCalled[0] = true;
+                throw new IOException("poo");
+            }
+
+        };
+
+        Package[] changes = scan.loadPackageChanges();
+        assertEquals(0, changes.length);
+        assertEquals(true, fetchCalled[0]);
+
+    }
+
+    public void testColdStartWithError() throws Exception {
+        //this will show starting up and reading packages from the dir when the remote one doesn't respond
+        URLScanner scan = new URLScanner();
+        scan.listener = new MockListener();
+        File dir = RuleBaseAssemblerTest.getTempDirectory();
+
+        Package p1 = new Package("goo.ber");
+        Package p2 = new Package("wee.waa");
+
+        File f1 = URLScanner.getLocalCacheFileForURL( dir, new URL("http://goo.ber") );
+        File f2 = URLScanner.getLocalCacheFileForURL( dir, new URL("http://wee.waa") );
+
+        RuleBaseAssemblerTest.writePackage( p1, f1 );
+        RuleBaseAssemblerTest.writePackage( p2, f2 );
+
+        Properties config = new Properties();
+        config.setProperty( RuleAgent.LOCAL_URL_CACHE, dir.getPath() );
+        config.setProperty( RuleAgent.URLS, "http://goo.ber http://wee.waa" );
+
+        scan.configure( config );
+
+        scan.httpClient = new IHttpClient() {
+
+            public LastUpdatedPing checkLastUpdated(URL url) throws IOException {
+                throw new IOException();
+            }
+
+            public Package fetchPackage(URL url) throws IOException {
+                throw new IOException();
+            }
+
+        };
+
+        assertNotNull( scan.localCacheFileScanner );
+        assertNotNull( scan.localCacheDir );
+
+        RuleBase rb = RuleBaseFactory.newRuleBase();
+        PackageProvider.applyChanges( rb, true, scan.loadPackageChanges(), getNilListener() );
+        assertEquals(2, rb.getPackages().length);
+
+
+    }
+
+
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/BaseClassFieldExtractorFactoryTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/BaseClassFieldExtractorFactoryTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/BaseClassFieldExtractorFactoryTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,100 @@
+package org.drools.base;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import junit.framework.TestCase;
+
+import org.drools.spi.FieldExtractor;
+import org.drools.util.asm.BeanInherit;
+import org.drools.util.asm.TestAbstract;
+import org.drools.util.asm.TestAbstractImpl;
+import org.drools.util.asm.TestInterface;
+import org.drools.util.asm.TestInterfaceImpl;
+
+public class BaseClassFieldExtractorFactoryTest extends TestCase {
+
+    private ClassFieldExtractorCache cache;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        cache = ClassFieldExtractorCache.getInstance();
+    }
+
+    public void testIt() throws Exception {
+        ClassFieldExtractorFactory factory = new ClassFieldExtractorFactory();
+
+        FieldExtractor ex = factory.getClassFieldExtractor( TestBean.class,
+                                                            "name",
+                                                            Thread.currentThread().getContextClassLoader() );
+        assertEquals( 0,
+                      ex.getIndex() );
+        assertEquals( "michael",
+                      ex.getValue( null,
+                                   new TestBean() ) );
+        ex = factory.getClassFieldExtractor( TestBean.class,
+                                             "age",
+                                             Thread.currentThread().getContextClassLoader() );
+        assertEquals( 1,
+                      ex.getIndex() );
+        assertEquals( 42,
+                      ((Number) ex.getValue( null,
+                                             new TestBean() )).intValue() );
+
+    }
+
+    public void testInterface() throws Exception {
+        final FieldExtractor ex = cache.getExtractor( TestInterface.class,
+                                                      "something",
+                                                      getClass().getClassLoader() );
+        assertEquals( 0,
+                      ex.getIndex() );
+        assertEquals( "foo",
+                      ex.getValue( null,
+                                   new TestInterfaceImpl() ) );
+    }
+
+    public void testAbstract() throws Exception {
+        final FieldExtractor ex = cache.getExtractor( TestAbstract.class,
+                                                      "something",
+                                                      getClass().getClassLoader() );
+        assertEquals( 0,
+                      ex.getIndex() );
+        assertEquals( "foo",
+                      ex.getValue( null,
+                                   new TestAbstractImpl() ) );
+    }
+
+    public void testInherited() throws Exception {
+        final FieldExtractor ex = cache.getExtractor( BeanInherit.class,
+                                                      "text",
+                                                      getClass().getClassLoader() );
+        assertEquals( "hola",
+                      ex.getValue( null,
+                                   new BeanInherit() ) );
+    }
+
+    public void testSelfReference() throws Exception {
+        final FieldExtractor ex = cache.getExtractor( BeanInherit.class,
+                                                      "this",
+                                                      getClass().getClassLoader() );
+        final TestBean bean = new TestBean();
+        assertEquals( bean,
+                      ex.getValue( null,
+                                   bean ) );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/ClassFieldExtractorTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/ClassFieldExtractorTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/ClassFieldExtractorTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,148 @@
+package org.drools.base;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import junit.framework.TestCase;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.util.asm.BeanInherit;
+import org.drools.util.asm.InterfaceChild;
+import org.drools.util.asm.TestAbstract;
+import org.drools.util.asm.TestAbstractImpl;
+import org.drools.util.asm.TestBean;
+import org.drools.util.asm.TestInterface;
+import org.drools.util.asm.TestInterfaceImpl;
+
+public class ClassFieldExtractorTest extends TestCase {
+
+    private ClassFieldExtractorCache cache;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        cache = ClassFieldExtractorCache.getInstance();
+    }
+
+    public void testBasic() throws Exception {
+        final Object[] objArray = new Object[1];
+
+        final TestBean obj = new TestBean();
+        obj.setBlah( false );
+        obj.setSomething( "no" );
+        obj.setObjArray( objArray );
+
+        final ClassFieldExtractor ext = cache.getExtractor( TestBean.class,
+                                                            "blah",
+                                                            getClass().getClassLoader() );
+        assertEquals( false,
+                      ((Boolean) ext.getValue( null,
+                                               obj )).booleanValue() );
+
+        final ClassFieldExtractor ext2 = cache.getExtractor( TestBean.class,
+                                                             "fooBar",
+                                                             getClass().getClassLoader() );
+        assertEquals( "fooBar",
+                      ext2.getValue( null,
+                                     obj ) );
+
+        final ClassFieldExtractor ext3 = cache.getExtractor( TestBean.class,
+                                                             "objArray",
+                                                             getClass().getClassLoader() );
+        assertEquals( objArray,
+                      ext3.getValue( null,
+                                     obj ) );
+
+    }
+
+    public void testInterface() throws Exception {
+
+        final TestInterface obj = new TestInterfaceImpl();
+        final ClassFieldExtractor ext = cache.getExtractor( TestInterface.class,
+                                                            "something",
+                                                            getClass().getClassLoader() );
+
+        assertEquals( "foo",
+                      (String) ext.getValue( null,
+                                             obj ) );
+
+    }
+
+    public void testAbstract() throws Exception {
+
+        final ClassFieldExtractor ext = cache.getExtractor( TestAbstract.class,
+                                                            "something",
+                                                            getClass().getClassLoader() );
+        final TestAbstract obj = new TestAbstractImpl();
+        assertEquals( "foo",
+                      (String) ext.getValue( null,
+                                             obj ) );
+
+    }
+
+    public void testInherited() throws Exception {
+        final ClassFieldExtractor ext = cache.getExtractor( BeanInherit.class,
+                                                            "text",
+                                                            getClass().getClassLoader() );
+        final BeanInherit obj = new BeanInherit();
+        assertEquals( "hola",
+                      (String) ext.getValue( null,
+                                             obj ) );
+
+    }
+
+    public void testMultipleInterfaces() throws Exception {
+        final ConcreteChild obj = new ConcreteChild();
+        final ClassFieldExtractor ext = cache.getExtractor( InterfaceChild.class,
+                                                            "foo",
+                                                            getClass().getClassLoader() );
+        assertEquals( 42,
+                      ((Number) ext.getValue( null,
+                                              obj )).intValue() );
+    }
+
+    public void testLong() throws Exception {
+        final ClassFieldExtractor ext = cache.getExtractor( TestBean.class,
+                                                            "longField",
+                                                            getClass().getClassLoader() );
+        final TestBean bean = new TestBean();
+        assertEquals( 424242,
+                      ((Number) ext.getValue( null,
+                                              bean )).longValue() );
+    }
+
+    public void testNonExistentField() throws Exception {
+        final Object[] objArray = new Object[1];
+
+        final TestBean obj = new TestBean();
+        obj.setBlah( false );
+        obj.setSomething( "no" );
+        obj.setObjArray( objArray );
+
+        try {
+            final ClassFieldExtractor ext = cache.getExtractor( TestBean.class,
+                                                                "xyz",
+                                                                getClass().getClassLoader() );
+            fail( "A RuntimeDroolsException should have been raised" );
+        } catch ( RuntimeDroolsException e ) {
+            e.printStackTrace();
+            // everything is fine, since field does not exist
+        } catch ( Exception e ) {
+            fail( "A RuntimeDroolsException should have been raised" );
+        }
+
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/ConcreteChild.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/ConcreteChild.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/ConcreteChild.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,44 @@
+package org.drools.base;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.util.asm.InterfaceChild;
+
+public class ConcreteChild
+    implements
+    InterfaceChild {
+
+    public String getBar() {
+
+        return "hola";
+    }
+
+    public int getFoo() {
+
+        return 42;
+    }
+
+    public int getBaz() {
+
+        return 42;
+    }
+
+    public String getURI() {
+        return "xxx";
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/DelegateJavaFactHandlerTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/DelegateJavaFactHandlerTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/DelegateJavaFactHandlerTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,140 @@
+package org.drools.base;
+
+import java.lang.reflect.Field;
+
+import junit.framework.TestCase;
+
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+
+public class DelegateJavaFactHandlerTest extends TestCase {
+
+    public void test1Entry() throws Exception {
+        final DelegateJavaFactHandler handler = new DelegateJavaFactHandler();
+
+        final Field field = handler.getClass().getDeclaredField( "entries" );
+        field.setAccessible( true );
+
+        final WorkingMemory wm1 = RuleBaseFactory.newRuleBase().newStatefulSession();
+        handler.register( wm1 );
+
+        JavaFactRegistryEntry[] entries = (JavaFactRegistryEntry[]) field.get( handler );
+        assertEquals( 1,
+                      entries.length );
+
+        assertTrue( handler.isRegistered( wm1 ) );
+
+        assertEquals( 1,
+                      handler.listWorkingMemories().length );
+        assertSame( wm1,
+                    handler.listWorkingMemories()[0].getWorkingMemory() );
+
+        final WorkingMemory wm2 = RuleBaseFactory.newRuleBase().newStatefulSession();
+        assertFalse( handler.isRegistered( wm2 ) );
+
+        handler.unregister( wm1 );
+        assertFalse( handler.isRegistered( wm1 ) );
+        entries = (JavaFactRegistryEntry[]) field.get( handler );
+        assertNull( entries );
+    }
+
+    public void test2Entries() throws Exception {
+        final DelegateJavaFactHandler handler = new DelegateJavaFactHandler();
+
+        final Field field = handler.getClass().getDeclaredField( "entries" );
+        field.setAccessible( true );
+
+        final WorkingMemory wm1 = RuleBaseFactory.newRuleBase().newStatefulSession();
+        final WorkingMemory wm2 = RuleBaseFactory.newRuleBase().newStatefulSession();
+        handler.register( wm1 );
+        handler.register( wm2 );
+
+        JavaFactRegistryEntry[] entries = (JavaFactRegistryEntry[]) field.get( handler );
+        assertEquals( 2,
+                      entries.length );
+
+        assertTrue( handler.isRegistered( wm1 ) );
+        assertTrue( handler.isRegistered( wm2 ) );
+
+        assertEquals( 2,
+                      handler.listWorkingMemories().length );
+        assertSame( wm1,
+                    handler.listWorkingMemories()[0].getWorkingMemory() );
+        assertSame( wm2,
+                    handler.listWorkingMemories()[1].getWorkingMemory() );
+
+        handler.unregister( wm1 );
+        assertFalse( handler.isRegistered( wm1 ) );
+        entries = (JavaFactRegistryEntry[]) field.get( handler );
+        assertEquals( 1,
+                      entries.length );
+
+        handler.unregister( wm2 );
+        assertFalse( handler.isRegistered( wm2 ) );
+        entries = (JavaFactRegistryEntry[]) field.get( handler );
+        assertNull( entries );
+
+        // check  revererse
+        handler.register( wm1 );
+        handler.register( wm2 );
+
+        handler.unregister( wm2 );
+        assertFalse( handler.isRegistered( wm2 ) );
+        entries = (JavaFactRegistryEntry[]) field.get( handler );
+        assertEquals( 1,
+                      entries.length );
+
+        handler.unregister( wm1 );
+        assertFalse( handler.isRegistered( wm1 ) );
+        entries = (JavaFactRegistryEntry[]) field.get( handler );
+        assertNull( entries );
+    }
+
+    public void test3Entries() throws Exception {
+        final DelegateJavaFactHandler handler = new DelegateJavaFactHandler();
+
+        final Field field = handler.getClass().getDeclaredField( "entries" );
+        field.setAccessible( true );
+
+        final WorkingMemory wm1 = RuleBaseFactory.newRuleBase().newStatefulSession();
+        final WorkingMemory wm2 = RuleBaseFactory.newRuleBase().newStatefulSession();
+        final WorkingMemory wm3 = RuleBaseFactory.newRuleBase().newStatefulSession();
+        handler.register( wm1 );
+        handler.register( wm2 );
+        handler.register( wm3 );
+
+        JavaFactRegistryEntry[] entries = (JavaFactRegistryEntry[]) field.get( handler );
+        assertEquals( 3,
+                      entries.length );
+
+        assertTrue( handler.isRegistered( wm1 ) );
+        assertTrue( handler.isRegistered( wm2 ) );
+        assertTrue( handler.isRegistered( wm3 ) );
+
+        assertEquals( 3,
+                      handler.listWorkingMemories().length );
+        assertSame( wm1,
+                    handler.listWorkingMemories()[0].getWorkingMemory() );
+        assertSame( wm2,
+                    handler.listWorkingMemories()[1].getWorkingMemory() );
+        assertSame( wm3,
+                    handler.listWorkingMemories()[2].getWorkingMemory() );
+
+        handler.unregister( wm2 );
+        assertFalse( handler.isRegistered( wm2 ) );
+        entries = (JavaFactRegistryEntry[]) field.get( handler );
+        assertEquals( 2,
+                      entries.length );
+
+        handler.unregister( wm1 );
+        assertFalse( handler.isRegistered( wm1 ) );
+        entries = (JavaFactRegistryEntry[]) field.get( handler );
+        assertEquals( 1,
+                      entries.length );
+
+        handler.unregister( wm3 );
+        assertFalse( handler.isRegistered( wm3 ) );
+        entries = (JavaFactRegistryEntry[]) field.get( handler );
+        assertNull( entries );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/EvaluatorFactoryTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/EvaluatorFactoryTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/EvaluatorFactoryTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,912 @@
+package org.drools.base;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
+import junit.framework.TestCase;
+
+import org.drools.base.evaluators.EvaluatorRegistry;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.Declaration;
+import org.drools.rule.VariableRestriction.BooleanVariableContextEntry;
+import org.drools.rule.VariableRestriction.CharVariableContextEntry;
+import org.drools.rule.VariableRestriction.DoubleVariableContextEntry;
+import org.drools.rule.VariableRestriction.LongVariableContextEntry;
+import org.drools.rule.VariableRestriction.ObjectVariableContextEntry;
+import org.drools.rule.VariableRestriction.VariableContextEntry;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.FieldValue;
+
+/**
+ * Some test coverage goodness for the evaluators.
+ * Evaluator concrete instances are inside the factory at this time.
+ * @author Michael Neale
+ */
+public class EvaluatorFactoryTest extends TestCase {
+
+    private EvaluatorRegistry registry = new EvaluatorRegistry();
+
+    public void testObject() {
+
+        final List list = new ArrayList();
+        list.add( "foo" );
+        list.add( null );
+
+        Collection col = Arrays.asList( new String[] { "foo", "bar", null} );
+
+        final Object[][] data = {
+                                 {"foo", "==", "bar", Boolean.FALSE},
+                                 {"foo", "==", "foo", Boolean.TRUE},
+                                 {"foo", "!=", "bar", Boolean.TRUE},
+                                 {list, "contains", "foo", Boolean.TRUE},
+                                 {list, "contains", "bar", Boolean.FALSE},
+                                 {list, "contains", null, Boolean.TRUE},
+                                 {null, "contains", "bar", Boolean.FALSE},
+                                 {null, "contains", null, Boolean.FALSE},
+                                 {list, "==", null, Boolean.FALSE},
+                                 {list, "!=", null, Boolean.TRUE},
+                                 {null, "==", null, Boolean.TRUE},
+                                 {null, "==", list, Boolean.FALSE},
+                                 {null, "!=", list, Boolean.TRUE},
+                                 {null, "<", new Integer( 43 ), Boolean.FALSE},
+                                 {null, ">=", new Integer( -10 ), Boolean.FALSE},
+                                 {null, ">", new Integer( -10 ), Boolean.FALSE},
+                                 {null, "<=", new Integer( 42 ), Boolean.FALSE},
+                                 {new BigDecimal( "42.42" ), "<", new BigDecimal( "43" ), Boolean.TRUE},
+                                 {new BigDecimal( "42.42" ), ">", new BigDecimal( "43" ), Boolean.FALSE},
+                                 {new BigDecimal( "42.42" ), "<=", new BigDecimal( "42.42" ), Boolean.TRUE},
+                                 {new BigInteger( "42" ), ">=", new BigInteger( "43" ), Boolean.FALSE},
+                                 {new BigInteger( "42" ), ">=", new BigInteger( "43" ), Boolean.FALSE},
+                                 {list, "excludes", "baz", Boolean.TRUE},
+                                 {list, "excludes", "foo", Boolean.FALSE},
+                                 {"foo", "memberOf", col, Boolean.TRUE},
+                                 {"xyz", "memberOf", col, Boolean.FALSE},
+                                 {null, "memberOf", col, Boolean.TRUE},
+                                 {"foo", "memberOf", null, Boolean.FALSE},
+                                 {"foo", "not memberOf", col, Boolean.FALSE},
+                                 {"xyz", "not memberOf", col, Boolean.TRUE},
+                                 {null, "not memberOf", col, Boolean.FALSE},
+                                 {"foo", "not memberOf", null, Boolean.FALSE}
+
+        };
+
+        runEvaluatorTest( data,
+                          ValueType.OBJECT_TYPE );
+
+    }
+
+    public void testArrayType() {
+
+        final Object[] field = new Object[]{"foo", "bar"};
+
+        final Object[][] data = {{field, "==", new Object[]{"foo"}, Boolean.FALSE},
+                                 {field, "==", field, Boolean.TRUE},
+                                 {field, "!=", new Object[]{"foo"}, Boolean.TRUE},
+                                 {field, "contains", "foo", Boolean.TRUE},
+                                 {field, "contains", "xyz", Boolean.FALSE},
+                                 {field, "contains", null, Boolean.FALSE},
+                                 {null, "contains", "foo", Boolean.FALSE},
+                                 {field, "excludes", "foo", Boolean.FALSE},
+                                 {field, "excludes", "xyz", Boolean.TRUE},
+                                 {field, "excludes", null, Boolean.TRUE},
+                                 {null, "excludes", "foo", Boolean.TRUE},
+                                 {field, "!=", null, Boolean.TRUE},
+                                 {field, "==", null, Boolean.FALSE},
+                                 {null, "==", field, Boolean.FALSE},
+                                 {null, "==", null, Boolean.TRUE},
+                                 {null, "!=", field, Boolean.TRUE},
+                                 {null, "!=", null, Boolean.FALSE},
+                                 {"foo", "memberOf", field, Boolean.TRUE},
+                                 {"xyz", "memberOf", field, Boolean.FALSE},
+                                 {null, "memberOf", field, Boolean.FALSE},
+                                 {"foo", "memberOf", null, Boolean.FALSE},
+                                 {"foo", "not memberOf", field, Boolean.FALSE},
+                                 {"xyz", "not memberOf", field, Boolean.TRUE},
+                                 {null, "not memberOf", field, Boolean.TRUE},
+                                 {"foo", "not memberOf", null, Boolean.TRUE}
+                                 };
+
+        runEvaluatorTest( data,
+                          ValueType.ARRAY_TYPE );
+
+    }
+
+    public void testString() {
+
+        Collection col = Arrays.asList( new String[] { "foo", "bar", null} );
+
+        final Object[][] data = {{"foo", "==", "bar", Boolean.FALSE},
+                                 {"foo", "==", "foo", Boolean.TRUE},
+                                 {"foo", "!=", "bar", Boolean.TRUE},
+                                 {"something foo", "matches", ".*foo", Boolean.TRUE},
+                                 {"foo", "matches", ".*foo", Boolean.TRUE},
+                                 {"foo", "matches", "bar", Boolean.FALSE},
+                                 {null, "matches", ".*foo", Boolean.FALSE},
+                                 {"foo", "==", null, Boolean.FALSE},
+                                 {"foo", "!=", null, Boolean.TRUE},
+                                 {null, "==", null, Boolean.TRUE},
+                                 {"foo", "!=", null, Boolean.TRUE},
+                                 {null, "!=", "foo", Boolean.TRUE},
+                                 {null, "!=", null, Boolean.FALSE},
+                                 {"foo", "memberOf", col, Boolean.TRUE},
+                                 {"xyz", "memberOf", col, Boolean.FALSE},
+                                 {null, "memberOf", col, Boolean.TRUE},
+                                 {"foo", "memberOf", null, Boolean.FALSE},
+                                 {"foo", "not memberOf", col, Boolean.FALSE},
+                                 {"xyz", "not memberOf", col, Boolean.TRUE},
+                                 {null, "not memberOf", col, Boolean.FALSE},
+                                 {"foo", "not memberOf", null, Boolean.FALSE},
+                                 {"foobar", "soundslike", "fubar", Boolean.TRUE},
+                                 {"fubar", "soundslike", "foobar", Boolean.TRUE},
+                                 {"foobar", "soundslike", "wanklerotaryengine", Boolean.FALSE}
+                                 };
+
+        runEvaluatorTest( data,
+                          ValueType.STRING_TYPE );
+
+    }
+
+    public void testInteger() {
+
+        Collection col = new ArrayList();
+        col.add( new Integer(42) );
+        col.add( new Integer(45) );
+
+        final Object[][] data = {{new Integer( 42 ), "==", new Integer( 42 ), Boolean.TRUE},
+                                 {new Integer( 42 ), "<", new Integer( 43 ), Boolean.TRUE},
+                                 {new Integer( 42 ), ">=", new Integer( 41 ), Boolean.TRUE},
+                                 {new Integer( 42 ), "!=", new Integer( 41 ), Boolean.TRUE},
+                                 {new Integer( 42 ), ">", new Integer( 41 ), Boolean.TRUE},
+                                 {new Integer( 42 ), "<=", new Integer( 42 ), Boolean.TRUE},
+                                 {new Integer( 42 ), ">", new Integer( 100 ), Boolean.FALSE},
+                                 {new Integer( 42 ), "!=", null, Boolean.TRUE},
+                                 {new Integer( 42 ), "==", null, Boolean.FALSE},
+                                 {null, "==", null, Boolean.TRUE},
+                                 {null, "!=", null, Boolean.FALSE},
+                                 {null, "!=", new Integer( 42 ), Boolean.TRUE},
+                                 {null, "==", new Integer( 42 ), Boolean.FALSE},
+                                 {null, "<", new Integer( 43 ), Boolean.FALSE},
+                                 {null, ">=", new Integer( -10 ), Boolean.FALSE},
+                                 {null, ">", new Integer( -10 ), Boolean.FALSE},
+                                 {null, "<=", new Integer( 42 ), Boolean.FALSE},
+                                 {new Integer( 42 ), "memberOf", col, Boolean.TRUE},
+                                 {new Integer( 43 ), "memberOf", col, Boolean.FALSE},
+                                 {null, "memberOf", col, Boolean.FALSE},
+                                 {new Integer( 42 ), "memberOf", null, Boolean.FALSE},
+                                 {new Integer( 42 ), "not memberOf", col, Boolean.FALSE},
+                                 {new Integer( 43 ), "not memberOf", col, Boolean.TRUE},
+                                 {null, "not memberOf", col, Boolean.TRUE},
+                                 {new Integer( 42 ), "not memberOf", null, Boolean.FALSE}
+                                 };
+
+        runEvaluatorTest( data,
+                          ValueType.PINTEGER_TYPE );
+
+    }
+
+    public void testBigDecimal() {
+
+        final ValueType type = ValueType.determineValueType( BigDecimal.class );
+        assertSame( type,
+                    ValueType.BIG_DECIMAL_TYPE );
+
+        Collection col = new ArrayList();
+        col.add( new BigDecimal(42) );
+        col.add( new BigDecimal(45) );
+
+        final Object[][] data = {{new BigDecimal( 42 ), "==", new BigDecimal( 42 ), Boolean.TRUE},
+                                 {new BigDecimal( 42 ), "<", new BigDecimal( 43 ), Boolean.TRUE},
+                                 {new BigDecimal( 42 ), ">=", new BigDecimal( 41 ), Boolean.TRUE},
+                                 {new BigDecimal( 42 ), "!=", new BigDecimal( 41 ), Boolean.TRUE},
+                                 {new BigDecimal( 42 ), ">", new BigDecimal( 41 ), Boolean.TRUE},
+                                 {new BigDecimal( 42 ), "<=", new BigDecimal( 42 ), Boolean.TRUE},
+                                 {new BigDecimal( 42 ), ">", new BigDecimal( 100 ), Boolean.FALSE},
+                                 {new BigDecimal( 42 ), "==", null, Boolean.FALSE},
+                                 {new BigDecimal( 42 ), "!=", null, Boolean.TRUE},
+                                 {null, "==", new BigDecimal( 42 ), Boolean.FALSE},
+                                 {null, "!=", new BigDecimal( 42 ), Boolean.TRUE},
+                                 {null, "<", new BigDecimal( 43 ), Boolean.FALSE},
+                                 {null, ">=", new BigDecimal( -10 ), Boolean.FALSE},
+                                 {null, ">", new BigDecimal( -10 ), Boolean.FALSE},
+                                 {null, "<=", new BigDecimal( 42 ), Boolean.FALSE},
+                                 {new BigDecimal( 42 ), "memberOf", col, Boolean.TRUE},
+                                 {new BigDecimal( 43 ), "memberOf", col, Boolean.FALSE},
+                                 {null, "memberOf", col, Boolean.FALSE},
+                                 {new BigDecimal( 42 ), "memberOf", null, Boolean.FALSE},
+                                 {new BigDecimal( 42 ), "not memberOf", col, Boolean.FALSE},
+                                 {new BigDecimal( 43 ), "not memberOf", col, Boolean.TRUE},
+                                 {null, "not memberOf", col, Boolean.TRUE},
+                                 {new BigDecimal( 42 ), "not memberOf", null, Boolean.FALSE}
+                                 };
+
+        runEvaluatorTest( data,
+                          ValueType.BIG_DECIMAL_TYPE );
+
+    }
+
+    public void testBigInteger() {
+
+        final ValueType type = ValueType.determineValueType( BigInteger.class );
+        assertSame( type,
+                    ValueType.BIG_INTEGER_TYPE );
+
+        Collection col = new ArrayList();
+        col.add( new BigInteger("42") );
+        col.add( new BigInteger("45") );
+
+        final Object[][] data = {{new BigInteger( "42" ), "==", new BigInteger( "42" ), Boolean.TRUE},
+                                 {new BigInteger( "42" ), "<", new BigInteger( "43" ), Boolean.TRUE},
+                                 {new BigInteger( "42" ), ">=", new BigInteger( "41" ), Boolean.TRUE},
+                                 {new BigInteger( "42" ), "!=", new BigInteger( "41" ), Boolean.TRUE},
+                                 {new BigInteger( "42" ), ">", new BigInteger( "41" ), Boolean.TRUE},
+                                 {new BigInteger( "42" ), "<=", new BigInteger( "42" ), Boolean.TRUE},
+                                 {new BigInteger( "42" ), ">", new BigInteger( "100" ), Boolean.FALSE},
+                                 {new BigInteger( "42" ), "==", null, Boolean.FALSE},
+                                 {new BigInteger( "42" ), "!=", null, Boolean.TRUE},
+                                 {null, "==", new BigInteger( "42" ), Boolean.FALSE},
+                                 {null, "!=", new BigInteger( "42" ), Boolean.TRUE},
+                                 {null, "<", new BigInteger( "43" ), Boolean.FALSE},
+                                 {null, ">=", new BigInteger( "-10" ), Boolean.FALSE},
+                                 {null, ">", new BigInteger( "-10" ), Boolean.FALSE},
+                                 {null, "<=", new BigInteger( "42" ), Boolean.FALSE},
+                                 {new BigInteger( "42" ), "memberOf", col, Boolean.TRUE},
+                                 {new BigInteger( "43" ), "memberOf", col, Boolean.FALSE},
+                                 {null, "memberOf", col, Boolean.FALSE},
+                                 {new BigInteger( "42" ), "memberOf", null, Boolean.FALSE},
+                                 {new BigInteger( "42" ), "not memberOf", col, Boolean.FALSE},
+                                 {new BigInteger( "43" ), "not memberOf", col, Boolean.TRUE},
+                                 {null, "not memberOf", col, Boolean.TRUE},
+                                 {new BigInteger( "42" ), "not memberOf", null, Boolean.FALSE}
+                                 };
+
+        runEvaluatorTest( data,
+                          ValueType.BIG_INTEGER_TYPE );
+
+    }
+
+    public void testShort() {
+
+        Collection col = new ArrayList();
+        col.add( new Short( (short) 42) );
+        col.add( new Short( (short) 45) );
+
+        //Test data: Obj1, Operand, Obj2
+        final Object[][] data = {{new Short( (short) 42 ), "==", new Short( (short) 42 ), Boolean.TRUE},
+                                 {new Short( (short) 42 ), "<", new Short( (short) 43 ), Boolean.TRUE},
+                                 {new Short( (short) 42 ), ">=", new Short( (short) 41 ), Boolean.TRUE},
+                                 {new Short( (short) 42 ), "!=", new Short( (short) 41 ), Boolean.TRUE},
+                                 {new Short( (short) 42 ), "==", null, Boolean.FALSE},
+                                 {null, "==", null, Boolean.TRUE},
+                                 {null, "!=", null, Boolean.FALSE},
+                                 {null, "!=", new Short( (short) 42 ), Boolean.TRUE},
+                                 {null, "==", new Short( (short) 42 ), Boolean.FALSE},
+                                 {null, "<", new Short( (short)43 ), Boolean.FALSE},
+                                 {null, ">=", new Short( (short)-10 ), Boolean.FALSE},
+                                 {null, ">", new Short( (short)-10 ), Boolean.FALSE},
+                                 {null, "<=", new Short((short) 42 ), Boolean.FALSE},
+                                 {new Short( (short) 42 ), "memberOf", col, Boolean.TRUE},
+                                 {new Short( (short) 43 ), "memberOf", col, Boolean.FALSE},
+                                 {null, "memberOf", col, Boolean.FALSE},
+                                 {new Short( (short) 42 ), "memberOf", null, Boolean.FALSE},
+                                 {new Short( (short) 42 ), "not memberOf", col, Boolean.FALSE},
+                                 {new Short( (short) 43 ), "not memberOf", col, Boolean.TRUE},
+                                 {null, "not memberOf", col, Boolean.TRUE},
+                                 {new Short( (short) 42 ), "not memberOf", null, Boolean.FALSE}
+                                 };
+
+        runEvaluatorTest( data,
+                          ValueType.PSHORT_TYPE );
+    }
+
+    public void testBoolean() {
+
+        Collection col = new ArrayList();
+        col.add( new Boolean( true ) );
+        col.add( new Boolean( true ) );
+
+        //Test data: Obj1, Operand, Obj2
+        final Object[][] data = {{new Boolean( true ), "==", new Boolean( true ), Boolean.TRUE},
+                                 {new Boolean( false ), "!=", new Boolean( true ), Boolean.TRUE},
+                                 {new Boolean( true ), "==", new Boolean( false ), Boolean.FALSE},
+                                 {new Boolean( true ), "!=", new Boolean( false ), Boolean.TRUE},
+                                 {new Boolean( true ), "==", null, Boolean.FALSE},
+                                 {null, "==", null, Boolean.TRUE},
+                                 {null, "!=", null, Boolean.FALSE},
+                                 {null, "!=", new Boolean( true ), Boolean.TRUE},
+                                 {null, "==", new Boolean( true ), Boolean.FALSE},
+                                 {new Boolean( true ), "memberOf", col, Boolean.TRUE},
+                                 {new Boolean( false ), "memberOf", col, Boolean.FALSE},
+                                 {null, "memberOf", col, Boolean.FALSE},
+                                 {new Boolean( true ), "memberOf", null, Boolean.FALSE},
+                                 {new Boolean( true ), "not memberOf", col, Boolean.FALSE},
+                                 {new Boolean( false ), "not memberOf", col, Boolean.TRUE},
+                                 {null, "not memberOf", col, Boolean.TRUE},
+                                 {new Boolean( true ), "not memberOf", null, Boolean.FALSE}
+                                 };
+
+        runEvaluatorTest( data,
+                          ValueType.PBOOLEAN_TYPE );
+    }
+
+    public void testDouble() {
+        Collection col = new ArrayList();
+        col.add( new Double(42) );
+        col.add( new Double(45) );
+
+        final Object[][] data = {{new Double( 42 ), "==", new Double( 42 ), Boolean.TRUE},
+                                 {new Double( 42 ), "<", new Double( 43 ), Boolean.TRUE},
+                                 {new Double( 42 ), ">=", new Double( 41 ), Boolean.TRUE},
+                                 {new Double( 42 ), "!=", new Double( 41 ), Boolean.TRUE},
+                                 {new Double( 42 ), ">", new Double( 41 ), Boolean.TRUE},
+                                 {new Double( 42 ), ">=", new Double( 41 ), Boolean.TRUE},
+                                 {new Double( 42 ), ">=", new Double( 42 ), Boolean.TRUE},
+                                 {new Double( 42 ), ">=", new Double( 100 ), Boolean.FALSE},
+                                 {new Double( 42 ), "<", new Double( 1 ), Boolean.FALSE},
+                                 {new Double( 42 ), "==", null, Boolean.FALSE},
+                                 {null, "==", null, Boolean.TRUE},
+                                 {null, "!=", null, Boolean.FALSE},
+                                 {null, "!=", new Double( 42 ), Boolean.TRUE},
+                                 {null, "==", new Double( 42 ), Boolean.FALSE},
+                                 {null, "<", new Double( 43 ), Boolean.FALSE},
+                                 {null, ">=", new Double( -10 ), Boolean.FALSE},
+                                 {null, ">", new Double( -10 ), Boolean.FALSE},
+                                 {null, "<=", new Double( 42 ), Boolean.FALSE},
+                                 {new Double( 42 ), "memberOf", col, Boolean.TRUE},
+                                 {new Double( 43 ), "memberOf", col, Boolean.FALSE},
+                                 {null, "memberOf", col, Boolean.FALSE},
+                                 {new Double( 42 ), "memberOf", null, Boolean.FALSE},
+                                 {new Double( 42 ), "not memberOf", col, Boolean.FALSE},
+                                 {new Double( 43 ), "not memberOf", col, Boolean.TRUE},
+                                 {null, "not memberOf", col, Boolean.TRUE},
+                                 {new Double( 42 ), "not memberOf", null, Boolean.FALSE}
+                                 };
+
+        runEvaluatorTest( data,
+                          ValueType.PDOUBLE_TYPE );
+    }
+
+    public void testFloat() {
+        Collection col = new ArrayList();
+        col.add( new Float(42) );
+        col.add( new Float(45) );
+
+        final Object[][] data = {{new Float( 42 ), "==", new Float( 42 ), Boolean.TRUE},
+                                 {new Float( 42 ), "<", new Float( 43 ), Boolean.TRUE},
+                                 {new Float( 42 ), ">=", new Float( 41 ), Boolean.TRUE},
+                                 {new Float( 42 ), "!=", new Float( 41 ), Boolean.TRUE},
+                                 {new Float( 42 ), ">", new Float( 41 ), Boolean.TRUE},
+                                 {new Float( 42 ), ">=", new Float( 41 ), Boolean.TRUE},
+                                 {new Float( 42 ), ">=", new Float( 42 ), Boolean.TRUE},
+                                 {new Float( 42 ), ">=", new Float( 100 ), Boolean.FALSE},
+                                 {new Float( 42 ), "<", new Float( 1 ), Boolean.FALSE},
+                                 {new Float( 42 ), "==", null, Boolean.FALSE},
+                                 {null, "==", null, Boolean.TRUE},
+                                 {null, "!=", null, Boolean.FALSE},
+                                 {null, "!=", new Float( 42 ), Boolean.TRUE},
+                                 {null, "==", new Float( 42 ), Boolean.FALSE},
+                                 {null, "<", new Float( 43 ), Boolean.FALSE},
+                                 {null, ">=", new Float( -10 ), Boolean.FALSE},
+                                 {null, ">", new Float( -10 ), Boolean.FALSE},
+                                 {null, "<=", new Float( 42 ), Boolean.FALSE},
+                                 {new Float( 42 ), "memberOf", col, Boolean.TRUE},
+                                 {new Float( 43 ), "memberOf", col, Boolean.FALSE},
+                                 {null, "memberOf", col, Boolean.FALSE},
+                                 {new Float( 42 ), "memberOf", null, Boolean.FALSE},
+                                 {new Float( 42 ), "not memberOf", col, Boolean.FALSE},
+                                 {new Float( 43 ), "not memberOf", col, Boolean.TRUE},
+                                 {null, "not memberOf", col, Boolean.TRUE},
+                                 {new Float( 42 ), "not memberOf", null, Boolean.FALSE}
+                                 };
+
+        runEvaluatorTest( data,
+                          ValueType.PFLOAT_TYPE );
+    }
+
+    public void testLong() {
+        Collection col = new ArrayList();
+        col.add( new Long(42) );
+        col.add( new Long(45) );
+
+        final Object[][] data = {{new Long( 42 ), "==", new Long( 42 ), Boolean.TRUE},
+                                 {new Long( 42 ), "<", new Long( 43 ), Boolean.TRUE},
+                                 {new Long( 42 ), ">=", new Long( 41 ), Boolean.TRUE},
+                                 {new Long( 42 ), "!=", new Long( 41 ), Boolean.TRUE},
+                                 {new Long( 42 ), ">", new Long( 41 ), Boolean.TRUE},
+                                 {new Long( 42 ), ">=", new Long( 41 ), Boolean.TRUE},
+                                 {new Long( 42 ), ">=", new Long( 42 ), Boolean.TRUE},
+                                 {new Long( 42 ), ">=", new Long( 100 ), Boolean.FALSE},
+                                 {new Long( 42 ), "<", new Long( 1 ), Boolean.FALSE},
+                                 {new Long( 42 ), "==", null, Boolean.FALSE},
+                                 {null, "==", null, Boolean.TRUE},
+                                 {null, "!=", null, Boolean.FALSE},
+                                 {null, "!=", new Long( 42 ), Boolean.TRUE},
+                                 {null, "==", new Long( 42 ), Boolean.FALSE},
+                                 {null, "<", new Long( 43 ), Boolean.FALSE},
+                                 {null, ">=", new Long( -10 ), Boolean.FALSE},
+                                 {null, ">", new Long( -10 ), Boolean.FALSE},
+                                 {null, "<=", new Long( 42 ), Boolean.FALSE},
+                                 {new Long( 42 ), "memberOf", col, Boolean.TRUE},
+                                 {new Long( 43 ), "memberOf", col, Boolean.FALSE},
+                                 {null, "memberOf", col, Boolean.FALSE},
+                                 {new Long( 42 ), "memberOf", null, Boolean.FALSE},
+                                 {new Long( 42 ), "not memberOf", col, Boolean.FALSE},
+                                 {new Long( 43 ), "not memberOf", col, Boolean.TRUE},
+                                 {null, "not memberOf", col, Boolean.TRUE},
+                                 {new Long( 42 ), "not memberOf", null, Boolean.FALSE}
+                                 };
+
+        runEvaluatorTest( data,
+                          ValueType.PLONG_TYPE );
+    }
+
+    public void testCharacter() {
+        Collection col = new ArrayList();
+        col.add( new Character( 'a' ) );
+        col.add( new Character( 'b' ) );
+
+        final Object[][] data = {{new Character( 'a' ), "==", new Character( 'a' ), Boolean.TRUE},
+                                 {new Character( 'a' ), "<", new Character( 'b' ), Boolean.TRUE},
+                                 {new Character( 'a' ), ">=", new Character( 'a' ), Boolean.TRUE},
+                                 {new Character( 'a' ), "!=", new Character( 'Z' ), Boolean.TRUE},
+                                 {new Character( 'z' ), ">", new Character( 'a' ), Boolean.TRUE},
+                                 {new Character( 'z' ), ">=", new Character( 'z' ), Boolean.TRUE},
+                                 {new Character( 'z' ), ">=", new Character( 'a' ), Boolean.TRUE},
+                                 {new Character( 'a' ), ">=", new Character( 'z' ), Boolean.FALSE},
+                                 {new Character( 'z' ), "<", new Character( 'a' ), Boolean.FALSE},
+                                 {new Character( 'z' ), "==", null, Boolean.FALSE},
+                                 {null, "==", null, Boolean.TRUE},
+                                 {null, "!=", null, Boolean.FALSE},
+                                 {null, "!=", new Character( 'z' ), Boolean.TRUE},
+                                 {null, "==", new Character( 'z' ), Boolean.FALSE},
+                                 {null, "<", new Character( 'a' ), Boolean.FALSE},
+                                 {null, ">=", new Character( '\0' ), Boolean.FALSE},
+                                 {null, ">", new Character( '\0' ), Boolean.FALSE},
+                                 {null, "<=", new Character( 'a' ), Boolean.FALSE},
+                                 {new Character( 'a' ), "memberOf", col, Boolean.TRUE},
+                                 {new Character( 'z' ), "memberOf", col, Boolean.FALSE},
+                                 {null, "memberOf", col, Boolean.FALSE},
+                                 {new Character( 'a' ), "memberOf", null, Boolean.FALSE},
+                                 {new Character( 'a' ), "not memberOf", col, Boolean.FALSE},
+                                 {new Character( 'z' ), "not memberOf", col, Boolean.TRUE},
+                                 {null, "not memberOf", col, Boolean.TRUE},
+                                 {new Character( 'a' ), "not memberOf", null, Boolean.FALSE}
+                                 };
+        runEvaluatorTest( data,
+                          ValueType.PCHAR_TYPE );
+    }
+
+    public void testDate() throws Exception {
+
+        final SimpleDateFormat df = new SimpleDateFormat( "dd-MMM-yyyy",
+                                                          Locale.ENGLISH );
+        Collection col = new ArrayList();
+        col.add( df.parse( "10-Jul-1974" ) );
+        col.add( df.parse( "11-Jul-1974" ) );
+
+        //note that strings are also allowed on the right
+        final Object[][] data = {{df.parse( "10-Jul-1974" ), "==", df.parse( "10-Jul-1974" ), Boolean.TRUE},
+                                 {df.parse( "10-Jul-1974" ), "<", df.parse( "11-Jul-1974" ), Boolean.TRUE},
+                                 {df.parse( "10-Jul-1974" ), ">=", df.parse( "10-Jul-1974" ), Boolean.TRUE},
+                                 {df.parse( "10-Jul-1974" ), "!=", df.parse( "11-Jul-1974" ), Boolean.TRUE},
+                                 {df.parse( "10-Jul-2000" ), ">", df.parse( "10-Jul-1974" ), Boolean.TRUE},
+                                 {df.parse( "10-Jul-1974" ), ">=", df.parse( "10-Jul-1974" ), Boolean.TRUE},
+                                 {df.parse( "11-Jul-1974" ), ">=", df.parse( "10-Jul-1974" ), Boolean.TRUE},
+                                 {df.parse( "10-Jul-1974" ), ">=", df.parse( "11-Jul-1974" ), Boolean.FALSE},
+                                 {df.parse( "10-Jul-2000" ), "<", df.parse( "10-Jul-1974" ), Boolean.FALSE},
+                                 {df.parse( "10-Jul-1974" ), "<", df.parse( "11-Jul-1974" ), Boolean.TRUE},
+                                 {df.parse( "10-Jul-1974" ), "==", null, Boolean.FALSE},
+                                 {df.parse( "10-Jul-1974" ), "!=", null, Boolean.TRUE},
+                                 {null, "==", null, Boolean.TRUE},
+                                 {null, "==", df.parse( "10-Jul-1974" ), Boolean.FALSE},
+                                 {null, "!=", null, Boolean.FALSE},
+                                 {null, "!=", df.parse( "10-Jul-1974" ), Boolean.TRUE},
+                                 {null, "<", df.parse( "10-Jul-1974" ), Boolean.FALSE},
+                                 {null, ">=", new Date(0), Boolean.FALSE},
+                                 {null, ">", new Date(0), Boolean.FALSE},
+                                 {null, "<=", df.parse( "10-Jul-1974" ), Boolean.FALSE},
+                                 {df.parse( "10-Jul-1974" ), "memberOf", col, Boolean.TRUE},
+                                 {df.parse( "15-Jul-1974" ), "memberOf", col, Boolean.FALSE},
+                                 {null, "memberOf", col, Boolean.FALSE},
+                                 {df.parse( "10-Jul-1974" ), "memberOf", null, Boolean.FALSE},
+                                 {df.parse( "10-Jul-1974" ), "not memberOf", col, Boolean.FALSE},
+                                 {df.parse( "15-Jul-1974" ), "not memberOf", col, Boolean.TRUE},
+                                 {null, "not memberOf", col, Boolean.TRUE},
+                                 {df.parse( "10-Jul-1974" ), "not memberOf", null, Boolean.FALSE}
+                                 };
+        runEvaluatorTest( data,
+                          ValueType.DATE_TYPE );
+    }
+
+    public void testByte() {
+        Collection col = new ArrayList();
+        col.add( new Byte( "1" ) );
+        col.add( new Byte( "2" ) );
+
+        final Object[][] data = {{new Byte( "1" ), "==", new Byte( "1" ), Boolean.TRUE},
+                                 {new Byte( "1" ), "==", new Byte( "2" ), Boolean.FALSE},
+                                 {new Byte( "1" ), "!=", new Byte( "2" ), Boolean.TRUE},
+                                 {new Byte( "1" ), "!=", new Byte( "1" ), Boolean.FALSE},
+                                 {new Byte( "1" ), "<=", new Byte( "1" ), Boolean.TRUE},
+                                 {new Byte( "1" ), "==", null, Boolean.FALSE},
+                                 {new Byte( "1" ), "<", new Byte( "2" ), Boolean.TRUE},
+                                 {new Byte( "2" ), ">=", new Byte( "1" ), Boolean.TRUE},
+                                 {new Byte( "2" ), ">", new Byte( "1" ), Boolean.TRUE},
+                                 {new Byte( "1" ), "<=", new Byte( "2" ), Boolean.TRUE},
+                                 {null, "==", null, Boolean.TRUE},
+                                 {null, "!=", null, Boolean.FALSE},
+                                 {null, "!=", new Byte( "1" ), Boolean.TRUE},
+                                 {null, "==", new Byte( "1" ), Boolean.FALSE},
+                                 {null, "<", new Byte( Byte.MAX_VALUE), Boolean.FALSE},
+                                 {null, ">=", new Byte( Byte.MIN_VALUE ), Boolean.FALSE},
+                                 {null, ">", new Byte( Byte.MIN_VALUE ), Boolean.FALSE},
+                                 {null, "<=", new Byte( Byte.MAX_VALUE ), Boolean.FALSE},
+                                 {new Byte( "1" ), "memberOf", col, Boolean.TRUE},
+                                 {new Byte( "3" ), "memberOf", col, Boolean.FALSE},
+                                 {null, "memberOf", col, Boolean.FALSE},
+                                 {new Byte( "1" ), "memberOf", null, Boolean.FALSE},
+                                 {new Byte( "1" ), "not memberOf", col, Boolean.FALSE},
+                                 {new Byte( "3" ), "not memberOf", col, Boolean.TRUE},
+                                 {null, "not memberOf", col, Boolean.TRUE},
+                                 {new Byte( "1" ), "not memberOf", null, Boolean.FALSE}
+                                 };
+        runEvaluatorTest( data,
+                          ValueType.PBYTE_TYPE );
+
+    }
+
+    /**
+     * Test utility to play the data through the evaluators.
+     * @param data The data to try out : Array of {arg1, operator, arg2}
+     * @param valueType The Evaluator.**_TYPE to test
+     */
+    private void runEvaluatorTest(final Object[][] data,
+                                  final ValueType valueType) {
+        final Extractor extractor = new MockExtractor();
+        for ( int i = 0; i < data.length; i++ ) {
+            final Object[] row = data[i];
+            boolean isNegated = ((String) row[1]).startsWith("not ");
+            String evaluatorStr =  isNegated ? ((String)row[1]).substring( 4 ) : (String)row[1];
+            final Evaluator evaluator = registry.getEvaluatorDefinition( evaluatorStr ).getEvaluator( valueType, evaluatorStr, isNegated, null );
+            checkEvaluatorMethodWithFieldValue( valueType,
+                                                extractor,
+                                                row,
+                                                evaluator );
+            checkEvaluatorMethodCachedRight( valueType,
+                                             extractor,
+                                             row,
+                                             evaluator );
+            checkEvaluatorMethodCachedLeft( valueType,
+                                            extractor,
+                                            row,
+                                            evaluator );
+            checkEvaluatorMethodWith2Extractors( valueType,
+                                                 extractor,
+                                                 row,
+                                                 evaluator );
+
+            assertEquals( valueType,
+                          evaluator.getValueType() );
+
+        }
+    }
+
+    /**
+     * @param valueType
+     * @param extractor
+     * @param row
+     * @param evaluator
+     */
+    private void checkEvaluatorMethodWithFieldValue(final ValueType valueType,
+                                                    final Extractor extractor,
+                                                    final Object[] row,
+                                                    final Evaluator evaluator) {
+        final FieldValue value = FieldFactory.getFieldValue( row[2] );
+        final boolean result = evaluator.evaluate( null,
+                                                   extractor,
+                                                   row[0], value );
+        final String message = "The evaluator type: [" + valueType + "] with FieldValue incorrectly returned " + result + " for [" + row[0] + " " + row[1] + " " + row[2] + "]. It was asserted to return " + row[3];
+
+        if ( row[3] == Boolean.TRUE ) {
+            assertTrue( message,
+                        result );
+        } else {
+            assertFalse( message,
+                         result );
+        }
+    }
+
+    /**
+     * @param valueType
+     * @param extractor
+     * @param row
+     * @param evaluator
+     */
+    private void checkEvaluatorMethodCachedRight(final ValueType valueType,
+                                                 final Extractor extractor,
+                                                 final Object[] row,
+                                                 final Evaluator evaluator) {
+        final VariableContextEntry context = this.getContextEntry( evaluator,
+                                                             (FieldExtractor) extractor,
+                                                             valueType,
+                                                             row );
+        final boolean result = evaluator.evaluateCachedRight( null,
+                                                              context, row[2] );
+        final String message = "The evaluator type: [" + valueType + "] with CachedRight incorrectly returned " + result + " for [" + row[0] + " " + row[1] + " " + row[2] + "]. It was asserted to return " + row[3];
+
+        if ( row[3] == Boolean.TRUE ) {
+            assertTrue( message,
+                        result );
+        } else {
+            assertFalse( message,
+                         result );
+        }
+    }
+
+    /**
+     * @param valueType
+     * @param extractor
+     * @param row
+     * @param evaluator
+     */
+    private void checkEvaluatorMethodCachedLeft(final ValueType valueType,
+                                                final Extractor extractor,
+                                                final Object[] row,
+                                                final Evaluator evaluator) {
+        final VariableContextEntry context = this.getContextEntry( evaluator,
+                                                                   (FieldExtractor) extractor,
+                                                             valueType,
+                                                             row );
+        final boolean result = evaluator.evaluateCachedLeft( null,
+                                                             context, row[0] );
+        final String message = "The evaluator type: [" + valueType + "] with CachedLeft incorrectly returned " + result + " for [" + row[0] + " " + row[1] + " " + row[2] + "]. It was asserted to return " + row[3];
+
+        if ( row[3] == Boolean.TRUE ) {
+            assertTrue( message,
+                        result );
+        } else {
+            assertFalse( message,
+                         result );
+        }
+    }
+
+    /**
+     * @param valueType
+     * @param extractor
+     * @param row
+     * @param evaluator
+     */
+    private void checkEvaluatorMethodWith2Extractors(final ValueType valueType,
+                                                     final Extractor extractor,
+                                                     final Object[] row,
+                                                     final Evaluator evaluator) {
+        final boolean result = evaluator.evaluate( null,
+                                                   extractor,
+                                                   row[0],
+                                                   extractor, row[2] );
+        final String message = "The evaluator type: [" + valueType + "] with 2 extractors incorrectly returned " + result + " for [" + row[0] + " " + row[1] + " " + row[2] + "]. It was asserted to return " + row[3];
+
+        if ( row[3] == Boolean.TRUE ) {
+            assertTrue( message,
+                        result );
+        } else {
+            assertFalse( message,
+                         result );
+        }
+    }
+
+    private VariableContextEntry getContextEntry(final Evaluator evaluator,
+                                                 final FieldExtractor extractor,
+                                                 final ValueType valueType,
+                                                 final Object[] row) {
+        final Declaration declaration = new Declaration( "test",
+                                                   extractor,
+                                                   null );
+        final ValueType coerced = evaluator.getCoercedValueType();
+        
+        if ( coerced.isIntegerNumber() ) {
+            final LongVariableContextEntry context = new LongVariableContextEntry( extractor,
+                                                                             declaration,
+                                                                             evaluator );
+
+            if (row[2] == null) {
+                context.leftNull = true;
+            } else {
+                context.left = ((Number) row[2]).longValue();
+            }
+
+            if (row[0] == null) {
+                context.rightNull = true;
+            } else {
+                context.right = ((Number) row[0]).longValue();
+            }
+            return context;
+        } else if ( coerced.isChar() ) {
+            final CharVariableContextEntry context = new CharVariableContextEntry( extractor,
+                                                                                   declaration,
+                                                                                   evaluator );
+
+            if (row[2] == null) {
+                context.leftNull = true;
+            } else {
+                context.left = ((Character) row[2]).charValue();
+            }
+
+            if (row[0] == null) {
+                context.rightNull = true;
+            } else {
+                context.right = ((Character) row[0]).charValue();
+            }
+            return context;
+        } else if ( coerced.isBoolean() ) {
+            final BooleanVariableContextEntry context = new BooleanVariableContextEntry( extractor,
+                                                                                   declaration,
+                                                                                   evaluator );
+
+            if (row[2] == null) {
+                context.leftNull = true;
+            } else {
+                context.left = ((Boolean) row[2]).booleanValue();
+            }
+
+            if (row[0] == null) {
+                context.rightNull = true;
+            } else {
+                context.right = ((Boolean) row[0]).booleanValue();
+            }
+            return context;
+        } else if ( coerced.isFloatNumber() ) {
+            final DoubleVariableContextEntry context = new DoubleVariableContextEntry( extractor,
+                                                                                 declaration,
+                                                                                 evaluator );
+            if (row[2] == null) {
+                context.leftNull = true;
+            } else {
+                context.left = ((Number) row[2]).doubleValue();
+            }
+
+            if (row[0] == null) {
+                context.rightNull = true;
+            } else {
+                context.right = ((Number) row[0]).doubleValue();
+            }
+            return context;
+        } else {
+            final ObjectVariableContextEntry context = new ObjectVariableContextEntry( extractor,
+                                                                                 declaration,
+                                                                                 evaluator );
+            if (row[2] == null) {
+                context.leftNull = true;
+            } else {
+                context.left = row[2];
+            }
+
+            if (row[0] == null) {
+                context.rightNull = true;
+            } else {
+                context.right = row[0];
+            }
+            return context;
+        }
+    }
+
+    private static class MockExtractor
+        implements
+        FieldExtractor {
+
+        private static final long serialVersionUID = 400L;
+
+        public boolean getBooleanValue(InternalWorkingMemory workingMemory, final Object object) {
+            return object != null ? ((Boolean) object).booleanValue() : false;
+        }
+
+        public byte getByteValue(InternalWorkingMemory workingMemory, final Object object) {
+            return object != null ? ((Number) object).byteValue() : (byte) 0;
+        }
+
+        public char getCharValue(InternalWorkingMemory workingMemory, final Object object) {
+            return object != null ? ((Character) object).charValue() : '\0';
+        }
+
+        public double getDoubleValue(InternalWorkingMemory workingMemory, final Object object) {
+            return object != null ? ((Number) object).doubleValue() : 0.0;
+        }
+
+        public Class getExtractToClass() {
+            return null;
+        }
+
+        public String getExtractToClassName() {
+            return null;
+        }
+
+        public float getFloatValue(InternalWorkingMemory workingMemory, final Object object) {
+            return object != null ? ((Number) object).floatValue() : (float) 0.0;
+        }
+
+        public int getHashCode(InternalWorkingMemory workingMemory, final Object object) {
+            return 0;
+        }
+
+        public int getIntValue(InternalWorkingMemory workingMemory, final Object object) {
+            return object != null ? ((Number) object).intValue() : 0;
+        }
+
+        public long getLongValue(InternalWorkingMemory workingMemory, final Object object) {
+            return object != null ? ((Number) object).longValue() : 0;
+        }
+
+        public Method getNativeReadMethod() {
+            return null;
+        }
+
+        public short getShortValue(InternalWorkingMemory workingMemory, final Object object) {
+            return object != null ? ((Number) object).shortValue() : (short) 0;
+        }
+
+        public Object getValue(InternalWorkingMemory workingMemory, final Object object) {
+            return object;
+        }
+
+        public boolean isNullValue(InternalWorkingMemory workingMemory, final Object object ) {
+            return object == null;
+        }
+
+        public ValueType getValueType() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        public int getIndex() {
+            return 0;
+        }
+
+        public boolean isGlobal() {
+            return false;
+        }
+
+    }
+
+    //    public void testRegexFoo() {
+    //        Pattern p = Pattern.compile( ".*foo" );
+    //        boolean b;
+    //        long start = System.currentTimeMillis();
+    //        for (int i = 0; i < 1000000; i++) {
+    //            b = ("something foo".matches( ".*foo" ));
+    //        }
+    //        System.out.println("time: " + (System.currentTimeMillis() - start));
+    //
+    //        start = System.currentTimeMillis();
+    //        for (int i = 0; i < 1000000; i++) {
+    //            Matcher m = p.matcher( "something foo" );
+    //            b = m.matches();
+    //        }
+    //        System.out.println("time: " + (System.currentTimeMillis() - start));
+    //    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/FieldFactoryTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/FieldFactoryTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/FieldFactoryTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,28 @@
+package org.drools.base;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import junit.framework.TestCase;
+
+import org.drools.spi.FieldValue;
+
+public class FieldFactoryTest extends TestCase {
+
+    public void testBigDecimal() {
+        final FieldValue val = FieldFactory.getFieldValue( "42.42",
+                                                           ValueType.BIG_DECIMAL_TYPE );
+        assertEquals( BigDecimal.class,
+                      val.getValue().getClass() );
+        assertTrue( val.getValue().equals( new BigDecimal( "42.42" ) ) );
+    }
+
+    public void testBigInteger() {
+        final FieldValue val = FieldFactory.getFieldValue( "424242",
+                                                           ValueType.BIG_INTEGER_TYPE );
+        assertEquals( BigInteger.class,
+                      val.getValue().getClass() );
+        assertTrue( val.getValue().equals( new BigInteger( "424242" ) ) );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/FieldValueTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/FieldValueTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/FieldValueTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,79 @@
+package org.drools.base;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.spi.FieldValue;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+public class FieldValueTest extends TestCase {
+    FieldValue field1;
+    FieldValue field2;
+    FieldValue field3;
+    FieldValue field4;
+    FieldValue field5;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        this.field1 = FieldFactory.getFieldValue( null );
+        this.field2 = FieldFactory.getFieldValue( null );
+        this.field3 = FieldFactory.getFieldValue( "A" );
+        this.field4 = FieldFactory.getFieldValue( "A" );
+        this.field5 = FieldFactory.getFieldValue( "B" );
+
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /*
+     * Test method for 'org.drools.base.FieldValue.hashCode()'
+     */
+    public void testHashCode() {
+        Assert.assertEquals( this.field1.hashCode(),
+                             this.field1.hashCode() );
+        Assert.assertEquals( this.field1.hashCode(),
+                             this.field2.hashCode() );
+        Assert.assertEquals( this.field3.hashCode(),
+                             this.field3.hashCode() );
+        Assert.assertEquals( this.field3.hashCode(),
+                             this.field4.hashCode() );
+        Assert.assertFalse( this.field1.hashCode() == this.field3.hashCode() );
+        Assert.assertFalse( this.field3.hashCode() == this.field1.hashCode() );
+        Assert.assertFalse( this.field3.hashCode() == this.field5.hashCode() );
+    }
+
+    /*
+     * Test method for 'org.drools.base.FieldValue.equals(Object)'
+     */
+    public void testEqualsObject() {
+        Assert.assertEquals( this.field1,
+                             this.field1 );
+        Assert.assertEquals( this.field1,
+                             this.field2 );
+        Assert.assertEquals( this.field3,
+                             this.field3 );
+        Assert.assertEquals( this.field3,
+                             this.field4 );
+        Assert.assertFalse( this.field1.equals( this.field3 ) );
+        Assert.assertFalse( this.field3.equals( this.field1 ) );
+        Assert.assertFalse( this.field3.equals( this.field5 ) );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/ShadowProxyFactoryTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/ShadowProxyFactoryTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/ShadowProxyFactoryTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,655 @@
+package org.drools.base;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.drools.Address;
+import org.drools.Cheese;
+import org.drools.CheeseEqual;
+import org.drools.CheeseInterface;
+import org.drools.Person;
+
+public class ShadowProxyFactoryTest extends TestCase {
+
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    public void testProxyForClass() {
+        try {
+            // creating original object
+            final String originalType = "stilton";
+            final int originalPrice = 15;
+            final Cheese cheese = new Cheese( originalType,
+                                              originalPrice );
+
+            // creating proxy
+            final Class proxy = ShadowProxyFactory.getProxy( Cheese.class );
+            final Cheese cheeseProxy = (Cheese) proxy.getConstructor( new Class[]{Cheese.class} ).newInstance( new Object[]{cheese} );
+
+            // proxy is proxying the values
+            Assert.assertEquals( originalType,
+                                 cheeseProxy.getType() );
+            Assert.assertEquals( originalPrice,
+                                 cheeseProxy.getPrice() );
+            Assert.assertSame( cheese,
+                               ((ShadowProxy) cheeseProxy).getShadowedObject() );
+
+            // proxy must recongnize the original object on equals()/hashcode() calls
+            //Assert.assertEquals( cheeseProxy.hashCode(), cheese.hashCode() );
+            Assert.assertEquals( cheeseProxy,
+                                 cheese );
+
+            // changing original values
+            final String actualType = "rotten stilton";
+            final int actualPrice = 1;
+            cheese.setType( actualType );
+            cheese.setPrice( actualPrice );
+
+            // proxy does not see changes
+            Assert.assertEquals( actualType,
+                                 cheese.getType() );
+            Assert.assertFalse( actualType.equals( cheeseProxy.getType() ) );
+            Assert.assertEquals( originalType,
+                                 cheeseProxy.getType() );
+            Assert.assertEquals( actualPrice,
+                                 cheese.getPrice() );
+            Assert.assertFalse( actualPrice == cheeseProxy.getPrice() );
+            Assert.assertEquals( originalPrice,
+                                 cheeseProxy.getPrice() );
+
+            // reseting proxy
+            ((ShadowProxy) cheeseProxy).updateProxy();
+
+            // now proxy see changes
+            Assert.assertEquals( actualType,
+                                 cheese.getType() );
+            Assert.assertEquals( actualType,
+                                 cheeseProxy.getType() );
+            Assert.assertFalse( originalType.equals( cheeseProxy.getType() ) );
+            Assert.assertEquals( actualPrice,
+                                 cheese.getPrice() );
+            Assert.assertEquals( actualPrice,
+                                 cheeseProxy.getPrice() );
+            Assert.assertFalse( originalPrice == cheeseProxy.getPrice() );
+
+        } catch ( final Exception e ) {
+            fail( "Error: " + e.getMessage() );
+        }
+    }
+
+    public void testProxyForInterface() {
+        try {
+            // creating original object
+            final String originalType = "stilton";
+            final int originalPrice = 15;
+            final Cheese cheese = new Cheese( originalType,
+                                              originalPrice );
+
+            // creating proxy
+            final Class proxy = ShadowProxyFactory.getProxy( CheeseInterface.class );
+            final CheeseInterface cheeseProxy = (CheeseInterface) proxy.getConstructor( new Class[]{CheeseInterface.class} ).newInstance( new Object[]{cheese} );
+
+            // proxy is proxying the values
+            Assert.assertEquals( originalType,
+                                 cheeseProxy.getType() );
+            Assert.assertEquals( originalPrice,
+                                 cheeseProxy.getPrice() );
+            Assert.assertSame( cheese,
+                               ((ShadowProxy) cheeseProxy).getShadowedObject() );
+
+            // changing original values
+            final String actualType = "rotten stilton";
+            final int actualPrice = 1;
+            cheese.setType( actualType );
+            cheese.setPrice( actualPrice );
+
+            // proxy does not see changes
+            Assert.assertEquals( actualType,
+                                 cheese.getType() );
+            Assert.assertFalse( actualType.equals( cheeseProxy.getType() ) );
+            Assert.assertEquals( originalType,
+                                 cheeseProxy.getType() );
+            Assert.assertEquals( actualPrice,
+                                 cheese.getPrice() );
+            Assert.assertFalse( actualPrice == cheeseProxy.getPrice() );
+            Assert.assertEquals( originalPrice,
+                                 cheeseProxy.getPrice() );
+
+            // reseting proxy
+            ((ShadowProxy) cheeseProxy).updateProxy();
+
+            // now proxy see changes
+            Assert.assertEquals( actualType,
+                                 cheese.getType() );
+            Assert.assertEquals( actualType,
+                                 cheeseProxy.getType() );
+            Assert.assertFalse( originalType.equals( cheeseProxy.getType() ) );
+            Assert.assertEquals( actualPrice,
+                                 cheese.getPrice() );
+            Assert.assertEquals( actualPrice,
+                                 cheeseProxy.getPrice() );
+            Assert.assertFalse( originalPrice == cheeseProxy.getPrice() );
+
+        } catch ( final Exception e ) {
+            fail( "Error: " + e.getMessage() );
+        }
+    }
+
+    public void testProxyForAPIClass() {
+        try {
+            // creating original object
+            final List list = new ArrayList();
+
+            // creating proxy
+            final Class proxy = ShadowProxyFactory.getProxy( ArrayList.class );
+            final List listProxy = (List) proxy.getConstructor( new Class[]{ArrayList.class} ).newInstance( new Object[]{list} );
+
+            // proxy is proxying the values
+            Assert.assertEquals( list,
+                                 listProxy );
+            Assert.assertSame( list,
+                               ((ShadowProxy) listProxy).getShadowedObject() );
+
+        } catch ( final Exception e ) {
+            fail( "Error: " + e.getMessage() );
+        }
+    }
+
+    public void testEqualsHashCodeForClass() {
+        try {
+            // creating original object
+            final String originalType = "stilton";
+            final int originalPrice = 15;
+            final Cheese cheese = new Cheese( originalType,
+                                              originalPrice );
+
+            // creating proxy
+            final Class proxy = ShadowProxyFactory.getProxy( Cheese.class );
+            final Cheese cheeseProxy1 = (Cheese) proxy.getConstructor( new Class[]{Cheese.class} ).newInstance( new Object[]{cheese} );
+            final Cheese cheeseProxy2 = (Cheese) proxy.getConstructor( new Class[]{Cheese.class} ).newInstance( new Object[]{cheese} );
+
+            int cheeseHash = cheese.hashCode();
+            Assert.assertEquals( cheeseProxy1,
+                                 cheeseProxy2 );
+            Assert.assertEquals( cheeseProxy2,
+                                 cheeseProxy1 );
+            Assert.assertEquals( cheeseHash,
+                                 cheeseProxy1.hashCode() );
+
+            // changing original values
+            final String actualType = "rotten stilton";
+            final int actualPrice = 1;
+            cheese.setType( actualType );
+            cheese.setPrice( actualPrice );
+
+            Assert.assertEquals( cheeseHash,
+                                 cheeseProxy1.hashCode() );
+
+            // updating proxy1
+            ((ShadowProxy) cheeseProxy1).updateProxy();
+            cheeseHash = cheese.hashCode();
+
+            Assert.assertEquals( cheeseHash,
+                                 cheeseProxy1.hashCode() );
+
+            // they are still identity equals
+            Assert.assertTrue( cheeseProxy1.equals( cheeseProxy2 ) );
+            Assert.assertTrue( cheeseProxy2.equals( cheeseProxy1 ) );
+
+            // updating proxy2
+            ((ShadowProxy) cheeseProxy2).updateProxy();
+
+            // now they are equal again
+            Assert.assertEquals( cheeseProxy1,
+                                 cheeseProxy2 );
+            Assert.assertEquals( cheeseProxy2,
+                                 cheeseProxy1 );
+
+        } catch ( final Exception e ) {
+            fail( "Error: " + e.getMessage() );
+        }
+    }
+
+    // TODO: find a new way to test hashcode
+    //    public void testEqualsHashCodeForClass2() {
+    //        try {
+    //            // creating original object
+    //            final TestBean bean = new TestBean();
+    //
+    //            // creating proxy
+    //            final Class proxy = ShadowProxyFactory.getProxy( TestBean.class );
+    //            final TestBean beanProxy1 = (TestBean) proxy.getConstructor( new Class[]{TestBean.class} ).newInstance( new Object[]{bean} );
+    //            final TestBean beanProxy2 = (TestBean) proxy.getConstructor( new Class[]{TestBean.class} ).newInstance( new Object[]{bean} );
+    //
+    //            Assert.assertEquals( beanProxy1, beanProxy2 );
+    //            Assert.assertEquals( beanProxy2, beanProxy1 );
+    //            Assert.assertEquals( -130900686 , beanProxy1.hashCode() );
+    //            
+    //        } catch ( final Exception e ) {
+    //            fail( "Error: " + e.getMessage() );
+    //        }
+    //    }
+
+    //    private int cheeseHashCode(final Cheese cheese) {
+    //        final int PRIME = 31;
+    //        int result = 1;
+    //        result = PRIME * result + ((cheese.getType() == null) ? 0 : cheese.getType().hashCode());
+    //        result = PRIME * result + cheese.getPrice();
+    //        return result;
+    //    }
+
+    public void testClassWithStaticMethod() {
+        try {
+            // creating original object
+            final String originalType = "stilton";
+            final int originalPrice = 15;
+            final Cheese cheese = new Cheese( originalType,
+                                              originalPrice );
+
+            // creating proxy
+            final Class proxy = ShadowProxyFactory.getProxy( Cheese.class );
+            final Cheese cheeseProxy1 = (Cheese) proxy.getConstructor( new Class[]{Cheese.class} ).newInstance( new Object[]{cheese} );
+            final Cheese cheeseProxy2 = (Cheese) proxy.getConstructor( new Class[]{Cheese.class} ).newInstance( new Object[]{cheese} );
+
+            final int cheesehash = cheese.hashCode();
+            Assert.assertEquals( cheeseProxy1,
+                                 cheeseProxy2 );
+            Assert.assertEquals( cheeseProxy2,
+                                 cheeseProxy1 );
+            Assert.assertEquals( cheesehash,
+                                 cheeseProxy1.hashCode() );
+
+        } catch ( final Exception e ) {
+            e.printStackTrace();
+            fail( "Error: " + e.getMessage() );
+        }
+    }
+
+    public void testClassWithDelegateMethodWithLongParam() {
+        try {
+            // creating original object
+            final String originalType = "stilton";
+            final int originalPrice = 15;
+            final Cheese cheese = new Cheese( originalType,
+                                              originalPrice );
+
+            // creating proxy
+            final Class proxy = ShadowProxyFactory.getProxy( Cheese.class );
+            final Cheese cheeseProxy1 = (Cheese) proxy.getConstructor( new Class[]{Cheese.class} ).newInstance( new Object[]{cheese} );
+            final Cheese cheeseProxy2 = (Cheese) proxy.getConstructor( new Class[]{Cheese.class} ).newInstance( new Object[]{cheese} );
+
+            final int cheesehash = cheese.hashCode();
+            Assert.assertEquals( cheeseProxy1,
+                                 cheeseProxy2 );
+            Assert.assertEquals( cheeseProxy2,
+                                 cheeseProxy1 );
+            Assert.assertEquals( cheesehash,
+                                 cheeseProxy1.hashCode() );
+
+        } catch ( final Exception e ) {
+            e.printStackTrace();
+            fail( "Error: " + e.getMessage() );
+        }
+    }
+
+    public void testProxyForCollections() {
+        try {
+            // creating original object
+            List originalList = new ArrayList();
+            originalList.add( "a" );
+            originalList.add( "b" );
+            originalList.add( "c" );
+            originalList.add( "d" );
+
+            // creating proxy
+            final Class proxy = ShadowProxyFactory.getProxy( originalList.getClass() );
+            final List listProxy = (List) proxy.getConstructor( new Class[]{originalList.getClass()} ).newInstance( new Object[]{originalList} );
+            ((ShadowProxy) listProxy).setShadowedObject( originalList );
+
+            // proxy is proxying the values
+            Assert.assertEquals( "a",
+                                 listProxy.get( 0 ) );
+            Assert.assertTrue( listProxy.contains( "c" ) );
+            Assert.assertSame( originalList,
+                               ((ShadowProxy) listProxy).getShadowedObject() );
+
+            // proxy must recongnize the original object on equals() calls
+            Assert.assertEquals( listProxy,
+                                 originalList );
+
+            originalList.remove( "c" );
+            originalList.add( "e" );
+            Assert.assertTrue( listProxy.contains( "c" ) );
+            Assert.assertFalse( listProxy.contains( "e" ) );
+
+            ((ShadowProxy) listProxy).updateProxy();
+            Assert.assertFalse( listProxy.contains( "c" ) );
+            Assert.assertTrue( listProxy.contains( "e" ) );
+
+            // proxy must recongnize the original object on equals() calls
+            Assert.assertEquals( listProxy,
+                                 originalList );
+        } catch ( final Exception e ) {
+            e.printStackTrace();
+            fail( "Error: " + e.getMessage() );
+        }
+    }
+
+    public void testProxyForMaps() {
+        try {
+            // creating original object
+            Map originalMap = new HashMap();
+            originalMap.put( "name",
+                             "Edson" );
+            originalMap.put( "surname",
+                             "Tirelli" );
+            originalMap.put( "age",
+                             "28" );
+
+            // creating proxy
+            final Class proxy = ShadowProxyFactory.getProxy( originalMap.getClass() );
+            final Map mapProxy = (Map) proxy.getConstructor( new Class[]{originalMap.getClass()} ).newInstance( new Object[]{originalMap} );
+            ((ShadowProxy) mapProxy).setShadowedObject( originalMap );
+
+            // proxy is proxying the values
+            Assert.assertEquals( "Edson",
+                                 mapProxy.get( "name" ) );
+            Assert.assertTrue( mapProxy.containsKey( "age" ) );
+            Assert.assertSame( originalMap,
+                               ((ShadowProxy) mapProxy).getShadowedObject() );
+
+            // proxy must recongnize the original object on equals() calls
+            Assert.assertEquals( mapProxy,
+                                 originalMap );
+
+            originalMap.remove( "age" );
+            originalMap.put( "hair",
+                             "brown" );
+            Assert.assertTrue( mapProxy.containsKey( "age" ) );
+            Assert.assertFalse( mapProxy.containsKey( "hair" ) );
+
+            ((ShadowProxy) mapProxy).updateProxy();
+            Assert.assertFalse( mapProxy.containsKey( "age" ) );
+            Assert.assertTrue( mapProxy.containsKey( "hair" ) );
+
+            // proxy must recongnize the original object on equals() calls
+            Assert.assertEquals( mapProxy,
+                                 originalMap );
+        } catch ( final Exception e ) {
+            e.printStackTrace();
+            fail( "Error: " + e.getMessage() );
+        }
+    }
+
+    public void testProxyForMapsAttributes() {
+        try {
+            Person bob = new Person( "bob",
+                                     30 );
+            Address addr1 = new Address( "street 1",
+                                         "111",
+                                         "11-1111-1111" );
+            Address addr2 = new Address( "street 2",
+                                         "222",
+                                         "22-2222-2222" );
+            Address addr3 = new Address( "street 3",
+                                         "333",
+                                         "33-3333-3333" );
+            Address addr4 = new Address( "street 4",
+                                         "444",
+                                         "44-4444-4444" );
+            Map addresses = new HashMap();
+            addresses.put( "home",
+                           addr1 );
+            addresses.put( "business",
+                           addr2 );
+            bob.setAddresses( addresses );
+
+            // creating proxy
+            final Class proxy = ShadowProxyFactory.getProxy( bob.getClass() );
+            final Person bobProxy = (Person) proxy.getConstructor( new Class[]{bob.getClass()} ).newInstance( new Object[]{bob} );
+            ((ShadowProxy) bobProxy).setShadowedObject( bob );
+
+            // proxy is proxying the values
+            Assert.assertEquals( bob.getAddresses().get( "business" ),
+                                 bobProxy.getAddresses().get( "business" ) );
+            Assert.assertSame( bob,
+                               ((ShadowProxy) bobProxy).getShadowedObject() );
+
+            // proxy must recongnize the original object on equals() calls
+            Assert.assertEquals( bobProxy,
+                                 bob );
+
+            bob.getAddresses().remove( "business" );
+            bob.getAddresses().put( "parents",
+                                    addr3 );
+            bob.getAddresses().put( "home",
+                                    addr4 );
+            Assert.assertTrue( bobProxy.getAddresses().containsKey( "business" ) );
+            Assert.assertFalse( bobProxy.getAddresses().containsKey( "parents" ) );
+            Assert.assertEquals( addr1,
+                                 bobProxy.getAddresses().get( "home" ) );
+
+            ((ShadowProxy) bobProxy).updateProxy();
+            Assert.assertFalse( bobProxy.getAddresses().containsKey( "business" ) );
+            Assert.assertTrue( bobProxy.getAddresses().containsKey( "parents" ) );
+            Assert.assertEquals( addr4,
+                                 bobProxy.getAddresses().get( "home" ) );
+
+            // proxy must recongnize the original object on equals() calls
+            Assert.assertEquals( bobProxy,
+                                 bob );
+        } catch ( final Exception e ) {
+            e.printStackTrace();
+            fail( "Error: " + e.getMessage() );
+        }
+    }
+
+    public void testProxyForCollectionAttributes() {
+        try {
+            Person bob = new Person( "bob",
+                                     30 );
+            Address addr1 = new Address( "street 1",
+                                         "111",
+                                         "11-1111-1111" );
+            Address addr2 = new Address( "street 2",
+                                         "222",
+                                         "22-2222-2222" );
+            Address addr3 = new Address( "street 3",
+                                         "333",
+                                         "33-3333-3333" );
+            bob.getAddressList().add( addr1 );
+            bob.getAddressList().add( addr2 );
+
+            // creating proxy
+            final Class proxy = ShadowProxyFactory.getProxy( bob.getClass() );
+            final Person bobProxy = (Person) proxy.getConstructor( new Class[]{bob.getClass()} ).newInstance( new Object[]{bob} );
+            ((ShadowProxy) bobProxy).setShadowedObject( bob );
+
+            // proxy is proxying the values
+            Assert.assertEquals( 2,
+                                 bobProxy.getAddressList().size() );
+            Assert.assertSame( bob,
+                               ((ShadowProxy) bobProxy).getShadowedObject() );
+
+            // proxy must recongnize the original object on equals() calls
+            Assert.assertEquals( bobProxy,
+                                 bob );
+
+            bob.getAddressList().remove( addr2 );
+            bob.getAddressList().add( addr3 );
+
+            Assert.assertTrue( bobProxy.getAddressList().contains( addr2 ) );
+            Assert.assertFalse( bobProxy.getAddressList().contains( addr3 ) );
+
+            ((ShadowProxy) bobProxy).updateProxy();
+            Assert.assertFalse( bobProxy.getAddressList().contains( addr2 ) );
+            Assert.assertTrue( bobProxy.getAddressList().contains( addr3 ) );
+
+            // proxy must recongnize the original object on equals() calls
+            Assert.assertEquals( bobProxy,
+                                 bob );
+        } catch ( final Exception e ) {
+            e.printStackTrace();
+            fail( "Error: " + e.getMessage() );
+        }
+    }
+
+    public void testProxyForArrayAttributes() {
+        try {
+            Person bob = new Person( "bob",
+                                     30 );
+            Address addr1 = new Address( "street 1",
+                                         "111",
+                                         "11-1111-1111" );
+            Address addr2 = new Address( "street 2",
+                                         "222",
+                                         "22-2222-2222" );
+            Address addr3 = new Address( "street 3",
+                                         "333",
+                                         "33-3333-3333" );
+            bob.getAddressArray()[0] = addr1;
+            bob.getAddressArray()[1] = addr2;
+
+            // creating proxy
+            final Class proxy = ShadowProxyFactory.getProxy( bob.getClass() );
+            final Person bobProxy = (Person) proxy.getConstructor( new Class[]{bob.getClass()} ).newInstance( new Object[]{bob} );
+            ((ShadowProxy) bobProxy).setShadowedObject( bob );
+
+            // proxy is proxying the values
+            Assert.assertEquals( addr1,
+                                 bobProxy.getAddressArray()[0] );
+            Assert.assertEquals( addr2,
+                                 bobProxy.getAddressArray()[1] );
+            Assert.assertSame( bob,
+                               ((ShadowProxy) bobProxy).getShadowedObject() );
+
+            // proxy must recongnize the original object on equals() calls
+            Assert.assertEquals( bobProxy,
+                                 bob );
+
+            bob.getAddressArray()[1] = addr3;
+
+            Assert.assertEquals( addr1,
+                                 bobProxy.getAddressArray()[0] );
+            Assert.assertEquals( addr2,
+                                 bobProxy.getAddressArray()[1] );
+
+            ((ShadowProxy) bobProxy).updateProxy();
+            Assert.assertEquals( addr1,
+                                 bobProxy.getAddressArray()[0] );
+            Assert.assertEquals( addr3,
+                                 bobProxy.getAddressArray()[1] );
+
+            // proxy must recongnize the original object on equals() calls
+            Assert.assertEquals( bobProxy,
+                                 bob );
+        } catch ( final Exception e ) {
+            e.printStackTrace();
+            fail( "Error: " + e.getMessage() );
+        }
+    }
+
+    public void testProxyForInterface2() {
+        try {
+            // creating original object
+            final String original = "stilton";
+
+            // creating proxy
+            final Class proxy = ShadowProxyFactory.getProxy( Comparable.class );
+            final Comparable comparableProxy = (Comparable) proxy.getConstructor( new Class[]{Comparable.class} ).newInstance( new Object[]{original} );
+
+            // proxy is proxying the values
+            Assert.assertEquals( comparableProxy,
+                                 original );
+            Assert.assertSame( original,
+                               ((ShadowProxy) comparableProxy).getShadowedObject() );
+            Assert.assertEquals( original.hashCode(),
+                                 comparableProxy.hashCode() );
+
+        } catch ( final Exception e ) {
+            fail( "Error: " + e.getMessage() );
+        }
+    }
+
+    public void testProxyForClassWithEquals() {
+        try {
+            // creating original object
+            final String originalType = "stilton";
+            final int originalPrice = 15;
+            final CheeseEqual cheese = new CheeseEqual( originalType,
+                                                        originalPrice );
+
+            // creating proxy
+            final Class proxy = ShadowProxyFactory.getProxy( CheeseEqual.class );
+            final CheeseEqual cheeseProxy = (CheeseEqual) proxy.getConstructor( new Class[]{CheeseEqual.class} ).newInstance( new Object[]{cheese} );
+
+            // proxy is proxying the values
+            Assert.assertEquals( originalType,
+                                 cheeseProxy.getType() );
+            Assert.assertEquals( originalPrice,
+                                 cheeseProxy.getPrice() );
+            Assert.assertSame( cheese,
+                               ((ShadowProxy) cheeseProxy).getShadowedObject() );
+
+            // proxy must recongnize the original object on equals()/hashcode() calls
+            //Assert.assertEquals( cheeseProxy.hashCode(), cheese.hashCode() );
+            Assert.assertEquals( cheeseProxy,
+                                 cheese );
+
+            // changing original values
+            final String actualType = "rotten stilton";
+            final int actualPrice = 1;
+            cheese.setType( actualType );
+            cheese.setPrice( actualPrice );
+
+            // proxy does not see changes
+            Assert.assertEquals( actualType,
+                                 cheese.getType() );
+            Assert.assertFalse( actualType.equals( cheeseProxy.getType() ) );
+            Assert.assertEquals( originalType,
+                                 cheeseProxy.getType() );
+            Assert.assertEquals( actualPrice,
+                                 cheese.getPrice() );
+            Assert.assertFalse( actualPrice == cheeseProxy.getPrice() );
+            Assert.assertEquals( originalPrice,
+                                 cheeseProxy.getPrice() );
+
+            // reseting proxy
+            ((ShadowProxy) cheeseProxy).updateProxy();
+
+            // now proxy see changes
+            Assert.assertEquals( actualType,
+                                 cheese.getType() );
+            Assert.assertEquals( actualType,
+                                 cheeseProxy.getType() );
+            Assert.assertFalse( originalType.equals( cheeseProxy.getType() ) );
+            Assert.assertEquals( actualPrice,
+                                 cheese.getPrice() );
+            Assert.assertEquals( actualPrice,
+                                 cheeseProxy.getPrice() );
+            Assert.assertFalse( originalPrice == cheeseProxy.getPrice() );
+
+            // Another cheese
+            final CheeseEqual cheese2 = new CheeseEqual( "brie",
+                                                        10 );
+            
+            final CheeseEqual cheese2Proxy = (CheeseEqual) proxy.getConstructor( new Class[]{CheeseEqual.class} ).newInstance( new Object[]{cheese2} );
+            assertFalse( cheeseProxy.equals( cheese2Proxy ) );
+            assertFalse( cheese2Proxy.equals( cheeseProxy ) );
+
+        } catch ( final Exception e ) {
+            fail( "Error: " + e.getMessage() );
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/TemporalEvaluatorFactoryTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/TemporalEvaluatorFactoryTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/TemporalEvaluatorFactoryTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,525 @@
+package org.drools.base;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.base.evaluators.EvaluatorDefinition;
+import org.drools.base.evaluators.EvaluatorRegistry;
+import org.drools.common.EventFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.Declaration;
+import org.drools.rule.VariableRestriction.BooleanVariableContextEntry;
+import org.drools.rule.VariableRestriction.CharVariableContextEntry;
+import org.drools.rule.VariableRestriction.DoubleVariableContextEntry;
+import org.drools.rule.VariableRestriction.LongVariableContextEntry;
+import org.drools.rule.VariableRestriction.ObjectVariableContextEntry;
+import org.drools.rule.VariableRestriction.VariableContextEntry;
+import org.drools.spi.Evaluator;
+import org.drools.spi.Extractor;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.FieldValue;
+
+import junit.framework.TestCase;
+
+/**
+ * Test coverage for the temporal evaluators.
+ * 
+ * @author Tino Breddin
+ */
+public class TemporalEvaluatorFactoryTest extends TestCase {
+
+	private EvaluatorRegistry registry = new EvaluatorRegistry();
+
+	public void testAfter() {
+		registry
+				.addEvaluatorDefinition("org.drools.base.evaluators.AfterEvaluatorDefinition");
+
+		EventFactHandle foo = new EventFactHandle(1, "foo", 1, 1, 2);
+		EventFactHandle bar = new EventFactHandle(2, "bar", 1, 4, 3);
+		EventFactHandle drool = new EventFactHandle(1, "drool", 1, 5, 2);
+
+		final Object[][] data = { { drool, "after", foo, Boolean.TRUE },
+				{ drool, "after", bar, Boolean.FALSE },
+				{ bar, "after", foo, Boolean.TRUE },
+				{ bar, "after", drool, Boolean.FALSE },
+				{ foo, "after", drool, Boolean.FALSE },
+				{ foo, "after", bar, Boolean.FALSE },
+				{ foo, "not after", bar, Boolean.TRUE },
+				{ foo, "not after", drool, Boolean.TRUE },
+				{ bar, "not after", drool, Boolean.TRUE },
+				{ bar, "not after", foo, Boolean.FALSE },
+				{ drool, "not after", foo, Boolean.FALSE },
+				{ drool, "not after", bar, Boolean.TRUE },
+				{ bar, "after[1]", foo, Boolean.TRUE },
+				{ bar, "after[0]", foo, Boolean.FALSE },
+				{ bar, "after[-3]", drool, Boolean.TRUE },
+				{ bar, "after[-4]", drool, Boolean.FALSE },
+				{ drool, "after[2]", foo, Boolean.TRUE },
+				{ drool, "after[1]", foo, Boolean.FALSE },
+				{ drool, "after[-2]", bar, Boolean.TRUE },
+				{ drool, "after[-3]", bar, Boolean.FALSE },
+				{ foo, "after[-6]", drool, Boolean.TRUE },
+				{ foo, "after[-7]", drool, Boolean.FALSE },
+				{ foo, "after[-6]", bar, Boolean.TRUE },
+				{ foo, "after[-7]", bar, Boolean.FALSE },
+				{ bar, "not after[1]", foo, Boolean.FALSE },
+				{ bar, "not after[0]", foo, Boolean.TRUE },
+				{ bar, "not after[-3]", drool, Boolean.FALSE },
+				{ bar, "not after[-4]", drool, Boolean.TRUE },
+				{ drool, "not after[2]", foo, Boolean.FALSE },
+				{ drool, "not after[1]", foo, Boolean.TRUE },
+				{ drool, "not after[-2]", bar, Boolean.FALSE },
+				{ drool, "not after[-3]", bar, Boolean.TRUE },
+				{ foo, "not after[-6]", drool, Boolean.FALSE },
+				{ foo, "not after[-7]", drool, Boolean.TRUE },
+				{ foo, "not after[-6]", bar, Boolean.FALSE },
+				{ foo, "not after[-7]", bar, Boolean.TRUE },
+				{ drool, "after[1,4]", foo, Boolean.TRUE },
+				{ drool, "after[3,6]", foo, Boolean.FALSE },
+				{ drool, "after[-3,1]", bar, Boolean.TRUE },
+				{ drool, "after[-1,3]", bar, Boolean.FALSE },
+				{ bar, "after[1,5]", foo, Boolean.TRUE },
+				{ bar, "after[2,5]", foo, Boolean.FALSE },
+				{ bar, "after[-3,0]", drool, Boolean.TRUE },
+				{ bar, "after[-2,1]", drool, Boolean.FALSE },
+				{ foo, "after[-7,-3]", bar, Boolean.TRUE },
+				{ foo, "after[-5,-1]", bar, Boolean.FALSE },
+				{ foo, "after[-6,-5]", drool, Boolean.TRUE },
+				{ foo, "after[-5,-4]", drool, Boolean.FALSE },
+				{ drool, "not after[1,4]", foo, Boolean.FALSE },
+				{ drool, "not after[3,6]", foo, Boolean.TRUE },
+				{ drool, "not after[-3,1]", bar, Boolean.FALSE },
+				{ drool, "not after[-1,3]", bar, Boolean.TRUE },
+				{ bar, "not after[1,5]", foo, Boolean.FALSE },
+				{ bar, "not after[2,5]", foo, Boolean.TRUE },
+				{ bar, "not after[-3,0]", drool, Boolean.FALSE },
+				{ bar, "not after[-2,1]", drool, Boolean.TRUE },
+				{ foo, "not after[-7,-3]", bar, Boolean.FALSE },
+				{ foo, "not after[-5,-1]", bar, Boolean.TRUE },
+				{ foo, "not after[-6,-5]", drool, Boolean.FALSE },
+				{ foo, "not after[-5,-4]", drool, Boolean.TRUE }, };
+
+		runEvaluatorTest(data, ValueType.OBJECT_TYPE);
+	}
+
+	public void testBefore() {
+		registry
+				.addEvaluatorDefinition("org.drools.base.evaluators.BeforeEvaluatorDefinition");
+
+		EventFactHandle foo = new EventFactHandle(1, "foo", 1, 1, 2);
+		EventFactHandle bar = new EventFactHandle(2, "bar", 1, 2, 2);
+		EventFactHandle drool = new EventFactHandle(1, "drool", 1, 5, 3);
+
+		final Object[][] data = { 
+				{ foo, "before", drool, Boolean.TRUE },
+				{ foo, "before", bar, Boolean.FALSE },
+				{ drool, "before", foo, Boolean.FALSE },
+				{ drool, "before", bar, Boolean.FALSE },
+				{ bar, "before", drool, Boolean.TRUE },
+				{ bar, "before", foo, Boolean.FALSE },
+				{ foo, "not before", drool, Boolean.FALSE },
+				{ foo, "not before", bar, Boolean.TRUE },
+				{ drool, "not before", foo, Boolean.TRUE },
+				{ drool, "not before", bar, Boolean.TRUE },
+				{ bar, "not before", drool, Boolean.FALSE },
+				{ bar, "not before", foo, Boolean.TRUE },
+				{ foo, "before[2]", drool, Boolean.TRUE },
+				{ foo, "before[3]", drool, Boolean.FALSE },
+				{ foo, "before[-1]", bar, Boolean.TRUE },
+				{ foo, "before[-2]", bar, Boolean.FALSE },
+				{ bar, "before[1]", drool, Boolean.TRUE },
+				{ bar, "before[2]", drool, Boolean.FALSE },
+				{ bar, "before[-3]", foo, Boolean.TRUE },
+				{ bar, "before[-2]", foo, Boolean.FALSE },
+				{ drool, "before[-6]", bar, Boolean.TRUE },
+				{ drool, "before[-5]", bar, Boolean.FALSE },
+				{ drool, "before[-7]", foo, Boolean.TRUE },
+				{ drool, "before[-8]", foo, Boolean.FALSE },
+				{ foo, "not before[2]", drool, Boolean.FALSE },
+				{ foo, "not before[3]", drool, Boolean.TRUE },
+				{ foo, "not before[-1]", bar, Boolean.FALSE },
+				{ foo, "not before[-2]", bar, Boolean.TRUE },
+				{ bar, "not before[1]", drool, Boolean.FALSE },
+				{ bar, "not before[2]", drool, Boolean.TRUE },
+				{ bar, "not before[-3]", foo, Boolean.FALSE },
+				{ bar, "not before[-2]", foo, Boolean.TRUE },
+				{ drool, "not before[-6]", bar, Boolean.FALSE },
+				{ drool, "not before[-5]", bar, Boolean.TRUE },
+				{ drool, "not before[-7]", foo, Boolean.FALSE },
+				{ drool, "not before[-8]", foo, Boolean.TRUE },
+				{ foo, "before[2,4]", drool, Boolean.TRUE },
+				{ foo, "before[3,4]", drool, Boolean.FALSE },
+				{ foo, "before[-1,1]", bar, Boolean.TRUE },
+				{ foo, "before[0,-2]", bar, Boolean.FALSE },
+				{ bar, "before[0,4]", drool, Boolean.TRUE },
+				{ bar, "before[2,4]", drool, Boolean.FALSE },
+				{ bar, "before[-4,0]", foo, Boolean.TRUE },
+				{ bar, "before[-2,0]", foo, Boolean.FALSE },
+				{ drool, "before[-6,-3]", bar, Boolean.TRUE },
+				{ drool, "before[-5,-3]", bar, Boolean.FALSE },
+				{ drool, "before[-7,-4]", foo, Boolean.TRUE },
+				{ drool, "before[-6,-4]", foo, Boolean.FALSE },
+				{ foo, "not before[2,4]", drool, Boolean.FALSE },
+				{ foo, "not before[3,4]", drool, Boolean.TRUE },
+				{ foo, "not before[-1,1]", bar, Boolean.FALSE },
+				{ foo, "not before[0,-2]", bar, Boolean.TRUE },
+				{ bar, "not before[0,4]", drool, Boolean.FALSE },
+				{ bar, "not before[2,4]", drool, Boolean.TRUE },
+				{ bar, "not before[-4,0]", foo, Boolean.FALSE },
+				{ bar, "not before[-2,0]", foo, Boolean.TRUE },
+				{ drool, "not before[-6,-3]", bar, Boolean.FALSE },
+				{ drool, "not before[-5,-3]", bar, Boolean.TRUE },
+				{ drool, "not before[-7,-4]", foo, Boolean.FALSE },
+				{ drool, "not before[-6,-4]", foo, Boolean.TRUE } };
+
+		runEvaluatorTest(data, ValueType.OBJECT_TYPE);
+	}
+	
+	public void testCoincides() {
+		registry
+				.addEvaluatorDefinition("org.drools.base.evaluators.CoincidesEvaluatorDefinition");
+
+		EventFactHandle foo = new EventFactHandle(1, "foo", 1, 2, 3);
+		EventFactHandle bar = new EventFactHandle(2, "bar", 1, 2, 3);
+		EventFactHandle drool = new EventFactHandle(1, "drool", 1, 2, 2);
+		EventFactHandle mole = new EventFactHandle(1, "mole", 1, 1, 2);
+
+		final Object[][] data = { 
+				{ foo, "coincides", bar, Boolean.TRUE },
+				{ foo, "coincides", drool, Boolean.FALSE },
+				{ foo, "coincides", mole, Boolean.FALSE },
+				{ drool, "coincides", mole, Boolean.FALSE },
+				{ foo, "not coincides", bar, Boolean.FALSE },
+				{ foo, "not coincides", drool, Boolean.TRUE },
+				{ foo, "not coincides", mole, Boolean.TRUE },
+				{ drool, "not coincides", mole, Boolean.TRUE },
+				{ foo, "coincides[1]", bar, Boolean.TRUE },
+				{ foo, "coincides[1]", drool, Boolean.TRUE },
+				{ foo, "coincides[2]", mole, Boolean.TRUE },
+				{ foo, "coincides[1]", mole, Boolean.FALSE },
+				{ drool, "coincides[1]", mole, Boolean.TRUE },
+				{ foo, "not coincides[1]", bar, Boolean.FALSE },
+				{ foo, "not coincides[1]", drool, Boolean.FALSE },
+				{ foo, "not coincides[2]", mole, Boolean.FALSE },
+				{ foo, "not coincides[1]", mole, Boolean.TRUE },
+				{ drool, "not coincides[1]", mole, Boolean.FALSE },
+				{ foo, "coincides[1,2]", bar, Boolean.TRUE },
+				{ foo, "coincides[0,1]", drool, Boolean.TRUE },
+				{ foo, "coincides[1,0]", drool, Boolean.FALSE },
+				{ foo, "coincides[1,2]", mole, Boolean.TRUE },
+				{ foo, "coincides[1,1]", mole, Boolean.FALSE},
+				{ drool, "coincides[1,1]", mole, Boolean.TRUE },
+				{ drool, "coincides[0,1]", mole, Boolean.FALSE },
+				{ foo, "not coincides[1,2]", bar, Boolean.FALSE },
+				{ foo, "not coincides[0,1]", drool, Boolean.FALSE },
+				{ foo, "not coincides[1,0]", drool, Boolean.TRUE},
+				{ foo, "not coincides[1,2]", mole, Boolean.FALSE },
+				{ foo, "not coincides[1,1]", mole, Boolean.TRUE },
+				{ drool, "not coincides[1,1]", mole, Boolean.FALSE },
+				{ drool, "not coincides[0,1]", mole, Boolean.TRUE }
+		};
+
+		runEvaluatorTest(data, ValueType.OBJECT_TYPE);
+	}
+
+	private void runEvaluatorTest(final Object[][] data,
+			final ValueType valueType) {
+		final Extractor extractor = new MockExtractor();
+		for (int i = 0; i < data.length; i++) {
+			final Object[] row = data[i];
+			boolean isNegated = ((String) row[1]).startsWith("not ");
+			System.out.println((String) row[1]);
+			String evaluatorStr = isNegated ? ((String) row[1]).substring(4)
+					: (String) row[1];
+			boolean isConstrained = evaluatorStr.endsWith("]");
+			String parameters = null;
+			if (isConstrained) {
+				parameters = evaluatorStr.split("\\[")[1];
+				evaluatorStr = evaluatorStr.split("\\[")[0];
+				parameters = parameters.split("\\]")[0];
+			}
+			EvaluatorDefinition evalDef = registry
+					.getEvaluatorDefinition(evaluatorStr);
+			assertNotNull(evalDef);
+			@SuppressWarnings("unused")
+			final Evaluator evaluator = evalDef.getEvaluator(valueType,
+					evaluatorStr, isNegated, parameters);
+			System.out.println(evaluator);
+
+			checkEvaluatorMethodWith2Extractors(valueType, extractor, row,
+					evaluator);
+			checkEvaluatorMethodCachedRight(valueType, extractor, row,
+					evaluator);
+			checkEvaluatorMethodCachedLeft(valueType, extractor, row, evaluator);
+			checkEvaluatorMethodWithFieldValue(valueType, extractor, row, evaluator);
+			
+
+			assertEquals(valueType, evaluator.getValueType());
+
+		}
+	}
+
+	private void checkEvaluatorMethodWith2Extractors(final ValueType valueType,
+			final Extractor extractor, final Object[] row,
+			final Evaluator evaluator) {
+		final boolean result = evaluator.evaluate(null, extractor, row[0],
+				extractor, row[2]);
+		final String message = "The evaluator type: [" + valueType
+				+ "] with 2 extractors incorrectly returned " + result
+				+ " for [" + row[0] + " " + row[1] + " " + row[2]
+				+ "]. It was asserted to return " + row[3];
+
+		if (row[3] == Boolean.TRUE) {
+			assertTrue(message, result);
+		} else {
+			assertFalse(message, result);
+		}
+	}
+
+	private void checkEvaluatorMethodCachedRight(final ValueType valueType,
+			final Extractor extractor, final Object[] row,
+			final Evaluator evaluator) {
+		final VariableContextEntry context = this.getContextEntry(evaluator,
+				(FieldExtractor) extractor, valueType, row);
+		final boolean result = evaluator.evaluateCachedRight(null, context,
+				row[2]);
+		final String message = "The evaluator type: [" + valueType
+				+ "] with CachedRight incorrectly returned " + result
+				+ " for [" + row[0] + " " + row[1] + " " + row[2]
+				+ "]. It was asserted to return " + row[3];
+
+		if (row[3] == Boolean.TRUE) {
+			assertTrue(message, result);
+		} else {
+			assertFalse(message, result);
+		}
+	}
+
+	private void checkEvaluatorMethodCachedLeft(final ValueType valueType,
+			final Extractor extractor, final Object[] row,
+			final Evaluator evaluator) {
+		final VariableContextEntry context = this.getContextEntry(evaluator,
+				(FieldExtractor) extractor, valueType, row);
+		final boolean result = evaluator.evaluateCachedLeft(null, context,
+				row[0]);
+		final String message = "The evaluator type: [" + valueType
+				+ "] with CachedLeft incorrectly returned " + result + " for ["
+				+ row[0] + " " + row[1] + " " + row[2]
+				+ "]. It was asserted to return " + row[3];
+
+		if (row[3] == Boolean.TRUE) {
+			assertTrue(message, result);
+		} else {
+			assertFalse(message, result);
+		}
+	}
+
+	private void checkEvaluatorMethodWithFieldValue(final ValueType valueType,
+			final Extractor extractor, final Object[] row,
+			final Evaluator evaluator) {
+		final FieldValue value = FieldFactory.getFieldValue(row[2]);
+		RuntimeDroolsException exc = null;
+		try {
+			final boolean result = evaluator.evaluate(null, extractor, row[0],
+				value);
+		} catch (RuntimeDroolsException e) {
+			exc = e;
+		}
+		assertNotNull(exc);
+	}
+
+	private VariableContextEntry getContextEntry(final Evaluator evaluator,
+			final FieldExtractor extractor, final ValueType valueType,
+			final Object[] row) {
+		final Declaration declaration = new Declaration("test", extractor, null);
+		final ValueType coerced = evaluator.getCoercedValueType();
+
+		if (coerced.isIntegerNumber()) {
+			final LongVariableContextEntry context = new LongVariableContextEntry(
+					extractor, declaration, evaluator);
+
+			if (row[2] == null) {
+				context.leftNull = true;
+			} else {
+				context.left = ((Number) row[2]).longValue();
+			}
+
+			if (row[0] == null) {
+				context.rightNull = true;
+			} else {
+				context.right = ((Number) row[0]).longValue();
+			}
+			return context;
+		} else if (coerced.isChar()) {
+			final CharVariableContextEntry context = new CharVariableContextEntry(
+					extractor, declaration, evaluator);
+
+			if (row[2] == null) {
+				context.leftNull = true;
+			} else {
+				context.left = ((Character) row[2]).charValue();
+			}
+
+			if (row[0] == null) {
+				context.rightNull = true;
+			} else {
+				context.right = ((Character) row[0]).charValue();
+			}
+			return context;
+		} else if (coerced.isBoolean()) {
+			final BooleanVariableContextEntry context = new BooleanVariableContextEntry(
+					extractor, declaration, evaluator);
+
+			if (row[2] == null) {
+				context.leftNull = true;
+			} else {
+				context.left = ((Boolean) row[2]).booleanValue();
+			}
+
+			if (row[0] == null) {
+				context.rightNull = true;
+			} else {
+				context.right = ((Boolean) row[0]).booleanValue();
+			}
+			return context;
+		} else if (coerced.isFloatNumber()) {
+			final DoubleVariableContextEntry context = new DoubleVariableContextEntry(
+					extractor, declaration, evaluator);
+			if (row[2] == null) {
+				context.leftNull = true;
+			} else {
+				context.left = ((Number) row[2]).doubleValue();
+			}
+
+			if (row[0] == null) {
+				context.rightNull = true;
+			} else {
+				context.right = ((Number) row[0]).doubleValue();
+			}
+			return context;
+		} else {
+			final ObjectVariableContextEntry context = new ObjectVariableContextEntry(
+					extractor, declaration, evaluator);
+			if (row[2] == null) {
+				context.leftNull = true;
+			} else {
+				context.left = row[2];
+			}
+
+			if (row[0] == null) {
+				context.rightNull = true;
+			} else {
+				context.right = row[0];
+			}
+			return context;
+		}
+	}
+
+	private static class MockExtractor implements FieldExtractor {
+
+		private static final long serialVersionUID = 400L;
+
+		public boolean getBooleanValue(InternalWorkingMemory workingMemory,
+				final Object object) {
+			return object != null ? ((Boolean) object).booleanValue() : false;
+		}
+
+		public byte getByteValue(InternalWorkingMemory workingMemory,
+				final Object object) {
+			return object != null ? ((Number) object).byteValue() : (byte) 0;
+		}
+
+		public char getCharValue(InternalWorkingMemory workingMemory,
+				final Object object) {
+			return object != null ? ((Character) object).charValue() : '\0';
+		}
+
+		public double getDoubleValue(InternalWorkingMemory workingMemory,
+				final Object object) {
+			return object != null ? ((Number) object).doubleValue() : 0.0;
+		}
+
+		public Class getExtractToClass() {
+			return null;
+		}
+
+		public String getExtractToClassName() {
+			return null;
+		}
+
+		public float getFloatValue(InternalWorkingMemory workingMemory,
+				final Object object) {
+			return object != null ? ((Number) object).floatValue()
+					: (float) 0.0;
+		}
+
+		public int getHashCode(InternalWorkingMemory workingMemory,
+				final Object object) {
+			return 0;
+		}
+
+		public int getIntValue(InternalWorkingMemory workingMemory,
+				final Object object) {
+			return object != null ? ((Number) object).intValue() : 0;
+		}
+
+		public long getLongValue(InternalWorkingMemory workingMemory,
+				final Object object) {
+			return object != null ? ((Number) object).longValue() : 0;
+		}
+
+		public Method getNativeReadMethod() {
+			return null;
+		}
+
+		public short getShortValue(InternalWorkingMemory workingMemory,
+				final Object object) {
+			return object != null ? ((Number) object).shortValue() : (short) 0;
+		}
+
+		public Object getValue(InternalWorkingMemory workingMemory,
+				final Object object) {
+			return object;
+		}
+
+		public boolean isNullValue(InternalWorkingMemory workingMemory,
+				final Object object) {
+			return object == null;
+		}
+
+		public ValueType getValueType() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		public int getIndex() {
+			return 0;
+		}
+
+		public boolean isGlobal() {
+			return false;
+		}
+
+	}
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/TestBean.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/TestBean.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/TestBean.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,84 @@
+package org.drools.base;
+
+import java.util.Collections;
+import java.util.List;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class TestBean {
+    private final String name        = "michael";
+    private final int    age         = 42;
+
+    private final boolean      booleanAttr = true;
+    private final byte         byteAttr    = 1;
+    private final char         charAttr    = 'a';
+    private final short        shortAttr   = 3;
+    private final int          intAttr     = 4;
+    private final long         longAttr    = 5;
+    private final float        floatAttr   = 6.0f;
+    private final double       doubleAttr  = 7.0;
+    private final List         listAttr    = Collections.EMPTY_LIST;
+    private final Object       nullAttr    = null;
+
+    public String getName() {
+        return this.name;
+    }
+
+    public int getAge() {
+        return this.age;
+    }
+
+    public boolean isBooleanAttr() {
+        return this.booleanAttr;
+    }
+
+    public byte getByteAttr() {
+        return this.byteAttr;
+    }
+
+    public char getCharAttr() {
+        return this.charAttr;
+    }
+
+    public double getDoubleAttr() {
+        return this.doubleAttr;
+    }
+
+    public float getFloatAttr() {
+        return this.floatAttr;
+    }
+
+    public int getIntAttr() {
+        return this.intAttr;
+    }
+
+    public List getListAttr() {
+        return this.listAttr;
+    }
+
+    public long getLongAttr() {
+        return this.longAttr;
+    }
+
+    public short getShortAttr() {
+        return this.shortAttr;
+    }
+
+    public Object getNullAttr() {
+        return this.nullAttr;
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/ValueTypeTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/ValueTypeTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/ValueTypeTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,37 @@
+package org.drools.base;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+public class ValueTypeTest extends TestCase {
+
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    public void testIsBoolean() {
+        Assert.assertTrue( ValueType.BOOLEAN_TYPE.isBoolean() );
+        Assert.assertTrue( ValueType.PBOOLEAN_TYPE.isBoolean() );
+    }
+
+    public void testIsNumber() {
+        Assert.assertTrue( ValueType.PBYTE_TYPE.isNumber() );
+        Assert.assertTrue( ValueType.PSHORT_TYPE.isNumber() );
+        Assert.assertTrue( ValueType.PINTEGER_TYPE.isNumber() );
+        Assert.assertTrue( ValueType.PLONG_TYPE.isNumber() );
+        Assert.assertTrue( ValueType.PFLOAT_TYPE.isNumber() );
+        Assert.assertTrue( ValueType.PDOUBLE_TYPE.isNumber() );
+        Assert.assertTrue( ValueType.BYTE_TYPE.isNumber() );
+        Assert.assertTrue( ValueType.SHORT_TYPE.isNumber() );
+        Assert.assertTrue( ValueType.INTEGER_TYPE.isNumber() );
+        Assert.assertTrue( ValueType.LONG_TYPE.isNumber() );
+        Assert.assertTrue( ValueType.FLOAT_TYPE.isNumber() );
+        Assert.assertTrue( ValueType.DOUBLE_TYPE.isNumber() );
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/dataproviders/TestVariable.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/dataproviders/TestVariable.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/dataproviders/TestVariable.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,24 @@
+package org.drools.base.dataproviders;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TestVariable {
+
+    public String helloWorld(final String a1,
+                             final int a2,
+                             final String a3) {
+        return a1 + a2 + a3;
+    }
+
+    public List otherMethod() {
+        final List list = new ArrayList();
+        list.add( "boo" );
+        return list;
+    }
+
+    public String helloWorld() {
+        return "another one";
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/BaseClassFieldExtractorsTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/BaseClassFieldExtractorsTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/BaseClassFieldExtractorsTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,27 @@
+package org.drools.base.extractors;
+
+import junit.framework.TestCase;
+
+public abstract class BaseClassFieldExtractorsTest extends TestCase {
+
+    public abstract void testGetBooleanValue();
+
+    public abstract void testGetByteValue();
+
+    public abstract void testGetCharValue();
+
+    public abstract void testGetShortValue();
+
+    public abstract void testGetIntValue();
+
+    public abstract void testGetLongValue();
+
+    public abstract void testGetFloatValue();
+
+    public abstract void testGetDoubleValue();
+
+    public abstract void testGetValue();
+    
+    public abstract void testIsNullValue();
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/BooleanClassFieldExtractorTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/BooleanClassFieldExtractorTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/BooleanClassFieldExtractorTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,116 @@
+package org.drools.base.extractors;
+
+import junit.framework.Assert;
+
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.TestBean;
+import org.drools.spi.Extractor;
+
+public class BooleanClassFieldExtractorTest extends BaseClassFieldExtractorsTest {
+    Extractor extractor = ClassFieldExtractorCache.getInstance().getExtractor( TestBean.class,
+                                                                               "booleanAttr",
+                                                                               getClass().getClassLoader() );
+    TestBean  bean      = new TestBean();
+
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    public void testGetBooleanValue() {
+        try {
+            Assert.assertTrue( this.extractor.getBooleanValue( null,
+                                                               this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw exception" );
+        }
+    }
+
+    public void testGetByteValue() {
+        try {
+            this.extractor.getByteValue( null,
+                                         this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetCharValue() {
+        try {
+            this.extractor.getCharValue( null,
+                                         this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetDoubleValue() {
+        try {
+            this.extractor.getDoubleValue( null,
+                                           this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetFloatValue() {
+        try {
+            this.extractor.getFloatValue( null,
+                                          this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetIntValue() {
+        try {
+            this.extractor.getIntValue( null,
+                                        this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetLongValue() {
+        try {
+            this.extractor.getLongValue( null,
+                                         this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetShortValue() {
+        try {
+            this.extractor.getShortValue( null,
+                                          this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetValue() {
+        try {
+            Assert.assertSame( Boolean.TRUE,
+                               this.extractor.getValue( null,
+                                                        this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testIsNullValue() {
+        try {
+            Assert.assertFalse( this.extractor.isNullValue( null,
+                                                            this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/ByteClassFieldExtractorTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/ByteClassFieldExtractorTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/ByteClassFieldExtractorTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,119 @@
+package org.drools.base.extractors;
+
+import junit.framework.Assert;
+
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.TestBean;
+import org.drools.spi.Extractor;
+
+public class ByteClassFieldExtractorTest extends BaseClassFieldExtractorsTest {
+    Extractor extractor = ClassFieldExtractorCache.getInstance().getExtractor( TestBean.class,
+                                                                               "byteAttr",
+                                                                               getClass().getClassLoader() );
+    TestBean  bean      = new TestBean();
+
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    public void testGetBooleanValue() {
+        try {
+            this.extractor.getBooleanValue( null,
+                                            this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetByteValue() {
+        try {
+            Assert.assertEquals( 1,
+                                 this.extractor.getByteValue( null,
+                                                              this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetCharValue() {
+        try {
+            this.extractor.getCharValue( null,
+                                         this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetDoubleValue() {
+        try {
+            Assert.assertEquals( 1.0,
+                                 this.extractor.getDoubleValue( null,
+                                                                this.bean ),
+                                 0.01 );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetFloatValue() {
+        try {
+            Assert.assertEquals( 1.0f,
+                                 this.extractor.getFloatValue( null,
+                                                               this.bean ),
+                                 0.01 );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetIntValue() {
+        try {
+            Assert.assertEquals( 1,
+                                 this.extractor.getIntValue( null,
+                                                             this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetLongValue() {
+        try {
+            Assert.assertEquals( 1,
+                                 this.extractor.getLongValue( null,
+                                                              this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetShortValue() {
+        try {
+            Assert.assertEquals( 1,
+                                 this.extractor.getShortValue( null,
+                                                               this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetValue() {
+        try {
+            Assert.assertEquals( 1,
+                                 ((Number) this.extractor.getValue( null,
+                                                                    this.bean )).byteValue() );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testIsNullValue() {
+        try {
+            Assert.assertFalse( this.extractor.isNullValue( null,
+                                                            this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/CharClassFieldExtractorTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/CharClassFieldExtractorTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/CharClassFieldExtractorTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,117 @@
+package org.drools.base.extractors;
+
+import junit.framework.Assert;
+
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.TestBean;
+import org.drools.spi.Extractor;
+
+public class CharClassFieldExtractorTest extends BaseClassFieldExtractorsTest {
+    Extractor extractor = ClassFieldExtractorCache.getInstance().getExtractor( TestBean.class,
+                                                                               "charAttr",
+                                                                               getClass().getClassLoader() );
+    TestBean  bean      = new TestBean();
+
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    public void testGetBooleanValue() {
+        try {
+            this.extractor.getBooleanValue( null,
+                                            this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetByteValue() {
+        try {
+            Assert.assertEquals( 'a',
+                                 this.extractor.getByteValue( null,
+                                                              this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw exception" );
+        }
+    }
+
+    public void testGetCharValue() {
+        try {
+            Assert.assertEquals( 'a',
+                                 this.extractor.getCharValue( null,
+                                                              this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw exception" );
+        }
+    }
+
+    public void testGetDoubleValue() {
+        try {
+            Assert.assertEquals( 'a',
+                                 (int) this.extractor.getDoubleValue( null,
+                                                                      this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw exception" );
+        }
+    }
+
+    public void testGetFloatValue() {
+        try {
+            Assert.assertEquals( 'a',
+                                 (int) this.extractor.getFloatValue( null,
+                                                                     this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw exception" );
+        }
+    }
+
+    public void testGetIntValue() {
+        try {
+            Assert.assertEquals( 'a',
+                                 this.extractor.getIntValue( null,
+                                                             this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw exception" );
+        }
+    }
+
+    public void testGetLongValue() {
+        try {
+            Assert.assertEquals( 'a',
+                                 (int) this.extractor.getLongValue( null,
+                                                                    this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw exception" );
+        }
+    }
+
+    public void testGetShortValue() {
+        try {
+            Assert.assertEquals( 'a',
+                                 this.extractor.getShortValue( null,
+                                                               this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw exception" );
+        }
+    }
+
+    public void testGetValue() {
+        try {
+            Assert.assertEquals( 'a',
+                                 ((Character) this.extractor.getValue( null,
+                                                                       this.bean )).charValue() );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testIsNullValue() {
+        try {
+            Assert.assertFalse( this.extractor.isNullValue( null,
+                                                            this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/DoubleClassFieldExtractorTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/DoubleClassFieldExtractorTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/DoubleClassFieldExtractorTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,123 @@
+package org.drools.base.extractors;
+
+import junit.framework.Assert;
+
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.TestBean;
+import org.drools.spi.Extractor;
+
+public class DoubleClassFieldExtractorTest extends BaseClassFieldExtractorsTest {
+    private static final double VALUE     = 7;
+
+    Extractor                   extractor = ClassFieldExtractorCache.getInstance().getExtractor( TestBean.class,
+                                                                                                 "doubleAttr",
+                                                                                                 getClass().getClassLoader() );
+    TestBean                    bean      = new TestBean();
+
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    public void testGetBooleanValue() {
+        try {
+            this.extractor.getBooleanValue( null,
+                                            this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetByteValue() {
+        try {
+            Assert.assertEquals( (byte) DoubleClassFieldExtractorTest.VALUE,
+                                 this.extractor.getByteValue( null,
+                                                              this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetCharValue() {
+        try {
+            this.extractor.getCharValue( null,
+                                         this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetDoubleValue() {
+        try {
+            Assert.assertEquals( DoubleClassFieldExtractorTest.VALUE,
+                                 this.extractor.getDoubleValue( null,
+                                                                this.bean ),
+                                 0.01 );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetFloatValue() {
+        try {
+            Assert.assertEquals( DoubleClassFieldExtractorTest.VALUE,
+                                 this.extractor.getFloatValue( null,
+                                                               this.bean ),
+                                 0.01 );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetIntValue() {
+        try {
+            Assert.assertEquals( (int) DoubleClassFieldExtractorTest.VALUE,
+                                 this.extractor.getIntValue( null,
+                                                             this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetLongValue() {
+        try {
+            Assert.assertEquals( (long) DoubleClassFieldExtractorTest.VALUE,
+                                 this.extractor.getLongValue( null,
+                                                              this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetShortValue() {
+        try {
+            Assert.assertEquals( (short) DoubleClassFieldExtractorTest.VALUE,
+                                 this.extractor.getShortValue( null,
+                                                               this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetValue() {
+        try {
+            Assert.assertEquals( new Double( DoubleClassFieldExtractorTest.VALUE ),
+                                 this.extractor.getValue( null,
+                                                          this.bean ) );
+            Assert.assertTrue( this.extractor.getValue( null,
+                                                        this.bean ) instanceof Double );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testIsNullValue() {
+        try {
+            Assert.assertFalse( this.extractor.isNullValue( null,
+                                                            this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/FloatClassFieldExtractorTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/FloatClassFieldExtractorTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/FloatClassFieldExtractorTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,123 @@
+package org.drools.base.extractors;
+
+import junit.framework.Assert;
+
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.TestBean;
+import org.drools.spi.Extractor;
+
+public class FloatClassFieldExtractorTest extends BaseClassFieldExtractorsTest {
+    private static final float VALUE     = 6;
+
+    Extractor                  extractor = ClassFieldExtractorCache.getInstance().getExtractor( TestBean.class,
+                                                                                                "floatAttr",
+                                                                                                getClass().getClassLoader() );
+    TestBean                   bean      = new TestBean();
+
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    public void testGetBooleanValue() {
+        try {
+            this.extractor.getBooleanValue( null,
+                                            this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetByteValue() {
+        try {
+            Assert.assertEquals( (byte) FloatClassFieldExtractorTest.VALUE,
+                                 this.extractor.getByteValue( null,
+                                                              this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetCharValue() {
+        try {
+            this.extractor.getCharValue( null,
+                                         this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetDoubleValue() {
+        try {
+            Assert.assertEquals( FloatClassFieldExtractorTest.VALUE,
+                                 this.extractor.getDoubleValue( null,
+                                                                this.bean ),
+                                 0.01 );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetFloatValue() {
+        try {
+            Assert.assertEquals( FloatClassFieldExtractorTest.VALUE,
+                                 this.extractor.getFloatValue( null,
+                                                               this.bean ),
+                                 0.01 );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetIntValue() {
+        try {
+            Assert.assertEquals( (int) FloatClassFieldExtractorTest.VALUE,
+                                 this.extractor.getIntValue( null,
+                                                             this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetLongValue() {
+        try {
+            Assert.assertEquals( (long) FloatClassFieldExtractorTest.VALUE,
+                                 this.extractor.getLongValue( null,
+                                                              this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetShortValue() {
+        try {
+            Assert.assertEquals( (short) FloatClassFieldExtractorTest.VALUE,
+                                 this.extractor.getShortValue( null,
+                                                               this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetValue() {
+        try {
+            Assert.assertEquals( new Float( FloatClassFieldExtractorTest.VALUE ),
+                                 this.extractor.getValue( null,
+                                                          this.bean ) );
+            Assert.assertTrue( this.extractor.getValue( null,
+                                                        this.bean ) instanceof Float );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testIsNullValue() {
+        try {
+            Assert.assertFalse( this.extractor.isNullValue( null,
+                                                            this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/IntClassFieldExtractorTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/IntClassFieldExtractorTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/IntClassFieldExtractorTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,121 @@
+package org.drools.base.extractors;
+
+import junit.framework.Assert;
+
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.TestBean;
+import org.drools.spi.Extractor;
+
+public class IntClassFieldExtractorTest extends BaseClassFieldExtractorsTest {
+    private static final int VALUE     = 4;
+
+    Extractor                extractor = ClassFieldExtractorCache.getInstance().getExtractor( TestBean.class,
+                                                                                              "intAttr",
+                                                                                              getClass().getClassLoader() );
+    TestBean                 bean      = new TestBean();
+
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    public void testGetBooleanValue() {
+        try {
+            this.extractor.getBooleanValue( null,
+                                            this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetByteValue() {
+        try {
+            Assert.assertEquals( IntClassFieldExtractorTest.VALUE,
+                                 this.extractor.getByteValue( null,
+                                                              this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetCharValue() {
+        try {
+            this.extractor.getCharValue( null,
+                                         this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetDoubleValue() {
+        try {
+            Assert.assertEquals( IntClassFieldExtractorTest.VALUE,
+                                 this.extractor.getDoubleValue( null,
+                                                                this.bean ),
+                                 0.01 );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetFloatValue() {
+        try {
+            Assert.assertEquals( IntClassFieldExtractorTest.VALUE,
+                                 this.extractor.getFloatValue( null,
+                                                               this.bean ),
+                                 0.01 );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetIntValue() {
+        try {
+            Assert.assertEquals( IntClassFieldExtractorTest.VALUE,
+                                 this.extractor.getIntValue( null,
+                                                             this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetLongValue() {
+        try {
+            Assert.assertEquals( IntClassFieldExtractorTest.VALUE,
+                                 this.extractor.getLongValue( null,
+                                                              this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetShortValue() {
+        try {
+            Assert.assertEquals( IntClassFieldExtractorTest.VALUE,
+                                 this.extractor.getShortValue( null,
+                                                               this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetValue() {
+        try {
+            Assert.assertEquals( IntClassFieldExtractorTest.VALUE,
+                                 ((Number) this.extractor.getValue( null,
+                                                                    this.bean )).intValue() );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testIsNullValue() {
+        try {
+            Assert.assertFalse( this.extractor.isNullValue( null,
+                                                            this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/LongClassFieldExtractorTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/LongClassFieldExtractorTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/LongClassFieldExtractorTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,123 @@
+package org.drools.base.extractors;
+
+import junit.framework.Assert;
+
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.TestBean;
+import org.drools.spi.Extractor;
+
+public class LongClassFieldExtractorTest extends BaseClassFieldExtractorsTest {
+    private static final long VALUE     = 5;
+
+    Extractor                 extractor = ClassFieldExtractorCache.getInstance().getExtractor( TestBean.class,
+                                                                                               "longAttr",
+                                                                                               getClass().getClassLoader() );
+    TestBean                  bean      = new TestBean();
+
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    public void testGetBooleanValue() {
+        try {
+            this.extractor.getBooleanValue( null,
+                                            this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetByteValue() {
+        try {
+            Assert.assertEquals( LongClassFieldExtractorTest.VALUE,
+                                 this.extractor.getByteValue( null,
+                                                              this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetCharValue() {
+        try {
+            this.extractor.getCharValue( null,
+                                         this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetDoubleValue() {
+        try {
+            Assert.assertEquals( LongClassFieldExtractorTest.VALUE,
+                                 this.extractor.getDoubleValue( null,
+                                                                this.bean ),
+                                 0.01 );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetFloatValue() {
+        try {
+            Assert.assertEquals( LongClassFieldExtractorTest.VALUE,
+                                 this.extractor.getFloatValue( null,
+                                                               this.bean ),
+                                 0.01 );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetIntValue() {
+        try {
+            Assert.assertEquals( LongClassFieldExtractorTest.VALUE,
+                                 this.extractor.getIntValue( null,
+                                                             this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetLongValue() {
+        try {
+            Assert.assertEquals( LongClassFieldExtractorTest.VALUE,
+                                 this.extractor.getLongValue( null,
+                                                              this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetShortValue() {
+        try {
+            Assert.assertEquals( LongClassFieldExtractorTest.VALUE,
+                                 this.extractor.getShortValue( null,
+                                                               this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetValue() {
+        try {
+            Assert.assertEquals( new Long( (short) LongClassFieldExtractorTest.VALUE ),
+                                 this.extractor.getValue( null,
+                                                          this.bean ) );
+            Assert.assertTrue( this.extractor.getValue( null,
+                                                        this.bean ) instanceof Long );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testIsNullValue() {
+        try {
+            Assert.assertFalse( this.extractor.isNullValue( null,
+                                                            this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/MVELClassFieldExtractorTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/MVELClassFieldExtractorTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/MVELClassFieldExtractorTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,141 @@
+package org.drools.base.extractors;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.drools.Address;
+import org.drools.Person;
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.spi.Extractor;
+
+public class MVELClassFieldExtractorTest extends TestCase {
+
+    Extractor extractor = ClassFieldExtractorCache.getInstance().getExtractor( Person.class,
+                                                                               "addresses['home'].street",
+                                                                               getClass().getClassLoader() );
+    Person    person    = null;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        person = new Person( "bob",
+                             30 );
+        Address business = new Address( "Business Street",
+                                        "999",
+                                        null );
+        Address home = new Address( "Home Street",
+                                    "555",
+                                    "55555555" );
+        person.getAddresses().put( "business",
+                                   business );
+        person.getAddresses().put( "home",
+                                   home );
+    }
+
+    public void testGetBooleanValue() {
+        try {
+            this.extractor.getBooleanValue( null,
+                                            this.person );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetByteValue() {
+        try {
+            this.extractor.getByteValue( null,
+                                         this.person );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetCharValue() {
+        try {
+            this.extractor.getCharValue( null,
+                                         this.person );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetDoubleValue() {
+        try {
+            this.extractor.getDoubleValue( null,
+                                           this.person );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetFloatValue() {
+        try {
+            this.extractor.getFloatValue( null,
+                                          this.person );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetIntValue() {
+        try {
+            this.extractor.getIntValue( null,
+                                        this.person );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetLongValue() {
+        try {
+            this.extractor.getLongValue( null,
+                                         this.person );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetShortValue() {
+        try {
+            this.extractor.getShortValue( null,
+                                          this.person );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetValue() {
+        try {
+            Assert.assertEquals( "Home Street",
+                                 this.extractor.getValue( null,
+                                                          this.person ) );
+            Assert.assertTrue( this.extractor.getValue( null,
+                                                        this.person ) instanceof String );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testIsNullValue() {
+        try {
+            Assert.assertFalse( this.extractor.isNullValue( null,
+                                                            this.person ) );
+
+            Extractor nullExtractor = ClassFieldExtractorCache.getInstance().getExtractor( Person.class,
+                                                                                           "addresses['business'].phone",
+                                                                                           getClass().getClassLoader() );
+            Assert.assertTrue( nullExtractor.isNullValue( null,
+                                                          this.person ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/ObjectClassFieldExtractorTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/ObjectClassFieldExtractorTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/ObjectClassFieldExtractorTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,129 @@
+package org.drools.base.extractors;
+
+import java.util.Collections;
+import java.util.List;
+
+import junit.framework.Assert;
+
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.TestBean;
+import org.drools.spi.Extractor;
+
+public class ObjectClassFieldExtractorTest extends BaseClassFieldExtractorsTest {
+
+    Extractor extractor = ClassFieldExtractorCache.getInstance().getExtractor( TestBean.class,
+                                                                               "listAttr",
+                                                                               getClass().getClassLoader() );
+    TestBean  bean      = new TestBean();
+
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    public void testGetBooleanValue() {
+        try {
+            this.extractor.getBooleanValue( null,
+                                            this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetByteValue() {
+        try {
+            this.extractor.getByteValue( null,
+                                         this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetCharValue() {
+        try {
+            this.extractor.getCharValue( null,
+                                         this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetDoubleValue() {
+        try {
+            this.extractor.getDoubleValue( null,
+                                           this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetFloatValue() {
+        try {
+            this.extractor.getFloatValue( null,
+                                          this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetIntValue() {
+        try {
+            this.extractor.getIntValue( null,
+                                        this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetLongValue() {
+        try {
+            this.extractor.getLongValue( null,
+                                         this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetShortValue() {
+        try {
+            this.extractor.getShortValue( null,
+                                          this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetValue() {
+        try {
+            Assert.assertEquals( Collections.EMPTY_LIST,
+                                 this.extractor.getValue( null,
+                                                          this.bean ) );
+            Assert.assertTrue( this.extractor.getValue( null,
+                                                        this.bean ) instanceof List );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testIsNullValue() {
+        try {
+            Assert.assertFalse( this.extractor.isNullValue( null,
+                                                            this.bean ) );
+
+            Extractor nullExtractor = ClassFieldExtractorCache.getInstance().getExtractor( TestBean.class,
+                                                                                           "nullAttr",
+                                                                                           getClass().getClassLoader() );
+            Assert.assertTrue( nullExtractor.isNullValue( null,
+                                                          this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/ShortClassFieldExtractorTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/ShortClassFieldExtractorTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/extractors/ShortClassFieldExtractorTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,121 @@
+package org.drools.base.extractors;
+
+import junit.framework.Assert;
+
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.TestBean;
+import org.drools.spi.Extractor;
+
+public class ShortClassFieldExtractorTest extends BaseClassFieldExtractorsTest {
+    private static final short VALUE     = 3;
+
+    Extractor                  extractor = ClassFieldExtractorCache.getInstance().getExtractor( TestBean.class,
+                                                                                                "shortAttr",
+                                                                                                getClass().getClassLoader() );
+    TestBean                   bean      = new TestBean();
+
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    public void testGetBooleanValue() {
+        try {
+            this.extractor.getBooleanValue( null,
+                                            this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetByteValue() {
+        try {
+            Assert.assertEquals( ShortClassFieldExtractorTest.VALUE,
+                                 this.extractor.getByteValue( null,
+                                                              this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetCharValue() {
+        try {
+            this.extractor.getCharValue( null,
+                                         this.bean );
+            fail( "Should have throw an exception" );
+        } catch ( final Exception e ) {
+            // success
+        }
+    }
+
+    public void testGetDoubleValue() {
+        try {
+            Assert.assertEquals( ShortClassFieldExtractorTest.VALUE,
+                                 this.extractor.getDoubleValue( null,
+                                                                this.bean ),
+                                 0.01 );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetFloatValue() {
+        try {
+            Assert.assertEquals( ShortClassFieldExtractorTest.VALUE,
+                                 this.extractor.getFloatValue( null,
+                                                               this.bean ),
+                                 0.01 );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetIntValue() {
+        try {
+            Assert.assertEquals( ShortClassFieldExtractorTest.VALUE,
+                                 this.extractor.getIntValue( null,
+                                                             this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetLongValue() {
+        try {
+            Assert.assertEquals( ShortClassFieldExtractorTest.VALUE,
+                                 this.extractor.getLongValue( null,
+                                                              this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetShortValue() {
+        try {
+            Assert.assertEquals( ShortClassFieldExtractorTest.VALUE,
+                                 this.extractor.getShortValue( null,
+                                                               this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testGetValue() {
+        try {
+            Assert.assertEquals( ShortClassFieldExtractorTest.VALUE,
+                                 ((Number) this.extractor.getValue( null,
+                                                                    this.bean )).shortValue() );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+
+    public void testIsNullValue() {
+        try {
+            Assert.assertFalse( this.extractor.isNullValue( null,
+                                                            this.bean ) );
+        } catch ( final Exception e ) {
+            fail( "Should not throw an exception" );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/mvel/MVELCalendarCoercionTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/mvel/MVELCalendarCoercionTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/mvel/MVELCalendarCoercionTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,32 @@
+package org.drools.base.mvel;
+
+import java.util.Calendar;
+import java.util.Date;
+
+import junit.framework.TestCase;
+
+import org.drools.util.DateUtils;
+
+public class MVELCalendarCoercionTest extends TestCase {
+
+    public void testCalendar() {
+        MVELCalendarCoercion co = new MVELCalendarCoercion();
+        assertTrue(co.canConvertFrom( Calendar.class ));
+        assertFalse(co.canConvertFrom( Number.class ));
+
+        Calendar d = Calendar.getInstance();
+        assertSame(d, co.convertFrom( d ));
+    }
+
+    public void testString() {
+        MVELCalendarCoercion co = new MVELCalendarCoercion();
+        assertTrue(co.canConvertFrom( Calendar.class ));
+
+        String dt = "10-Jul-1974";
+        Date dt_ = DateUtils.parseDate( dt );
+        Calendar cal = Calendar.getInstance();
+        cal.setTime( dt_ );
+        assertEquals(cal, co.convertFrom( dt ));
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/mvel/MVELDateCoercionTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/mvel/MVELDateCoercionTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/base/mvel/MVELDateCoercionTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,29 @@
+package org.drools.base.mvel;
+
+import java.util.Date;
+
+import junit.framework.TestCase;
+
+import org.drools.util.DateUtils;
+
+public class MVELDateCoercionTest extends TestCase {
+
+    public void testDate() {
+        MVELDateCoercion co = new MVELDateCoercion();
+        assertTrue(co.canConvertFrom( Date.class ));
+        assertFalse(co.canConvertFrom( Number.class ));
+
+        Date d = new Date();
+        assertSame(d, co.convertFrom( d ));
+    }
+
+    public void testString() {
+        MVELDateCoercion co = new MVELDateCoercion();
+        assertTrue(co.canConvertFrom( Date.class ));
+
+        String dt = "10-Jul-1974";
+        Date dt_ = DateUtils.parseDate( dt );
+        assertEquals(dt_, co.convertFrom( dt ));
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/BaseBetaConstraintsTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/BaseBetaConstraintsTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/BaseBetaConstraintsTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,148 @@
+package org.drools.common;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.drools.RuleBaseConfiguration;
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.ClassObjectType;
+import org.drools.base.evaluators.ComparableEvaluatorsDefinition;
+import org.drools.base.evaluators.EqualityEvaluatorsDefinition;
+import org.drools.base.evaluators.EvaluatorRegistry;
+import org.drools.base.evaluators.MatchesEvaluatorsDefinition;
+import org.drools.base.evaluators.Operator;
+import org.drools.base.evaluators.SetEvaluatorsDefinition;
+import org.drools.base.evaluators.SoundslikeEvaluatorsDefinition;
+import org.drools.reteoo.BetaMemory;
+import org.drools.rule.Declaration;
+import org.drools.rule.Pattern;
+import org.drools.rule.VariableConstraint;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldExtractor;
+import org.drools.util.FactHandleIndexHashTable;
+import org.drools.util.FactHashTable;
+import org.drools.util.LinkedList;
+import org.drools.util.LinkedListEntry;
+import org.drools.util.TupleHashTable;
+import org.drools.util.TupleIndexHashTable;
+import org.drools.util.AbstractHashTable.FieldIndex;
+import org.drools.util.AbstractHashTable.Index;
+
+public abstract class BaseBetaConstraintsTest extends TestCase {
+    
+    public static EvaluatorRegistry registry = new EvaluatorRegistry();
+    static {
+        registry.addEvaluatorDefinition( new EqualityEvaluatorsDefinition() );
+        registry.addEvaluatorDefinition( new ComparableEvaluatorsDefinition() );
+        registry.addEvaluatorDefinition( new SetEvaluatorsDefinition() );
+        registry.addEvaluatorDefinition( new MatchesEvaluatorsDefinition() );
+        registry.addEvaluatorDefinition( new SoundslikeEvaluatorsDefinition() );
+    }
+
+    protected BetaNodeFieldConstraint getConstraint(String identifier,
+                                                    Operator operator,
+                                                    String fieldName,
+                                                    Class clazz) {
+        FieldExtractor extractor = ClassFieldExtractorCache.getInstance().getExtractor( clazz,
+                                                                                        fieldName,
+                                                                                        getClass().getClassLoader() );
+        Declaration declaration = new Declaration( identifier,
+                                                   extractor,
+                                                   new Pattern( 0,
+                                                                new ClassObjectType( clazz ) ) );
+        Evaluator evaluator = registry.getEvaluatorDefinition( operator.getOperatorString() ).getEvaluator( extractor.getValueType(), 
+                                                                                                            operator.getOperatorString(), 
+                                                                                                            operator.isNegated(), 
+                                                                                                            null );
+        return new VariableConstraint( extractor,
+                                       declaration,
+                                       evaluator );
+    }
+
+    protected void checkBetaConstraints(VariableConstraint[] constraints,
+                                        Class cls) {
+        RuleBaseConfiguration config = new RuleBaseConfiguration();
+        int depth = config.getCompositeKeyDepth();
+
+        BetaConstraints betaConstraints = null;
+
+        try {
+            betaConstraints = (BetaConstraints) cls.getConstructor( new Class[]{BetaNodeFieldConstraint[].class, RuleBaseConfiguration.class} ).newInstance( new Object[]{constraints, config} );
+        } catch ( Exception e ) {
+            throw new RuntimeException( "could not invoke constructor for " + cls.getName() );
+        }
+
+        //BetaConstraints betaConstraints = new DefaultBetaConstraints(constraints, config );
+
+        constraints = convertToConstraints( betaConstraints.getConstraints() );
+
+        List list = new ArrayList();
+
+        // get indexed positions
+        for ( int i = 0; i < constraints.length && list.size() < depth; i++ ) {
+            if ( constraints[i].getEvaluator().getOperator() == Operator.EQUAL ) {
+                list.add( new Integer( i ) );
+            }
+        }
+
+        // convert to array
+        int[] indexedPositions = new int[list.size()];
+        for ( int i = 0; i < list.size(); i++ ) {
+            indexedPositions[i] = i;
+        }
+
+        assertEquals( (indexedPositions.length > 0),
+                      betaConstraints.isIndexed() );
+        assertEquals( indexedPositions.length,
+                      betaConstraints.getIndexCount() );
+        BetaMemory betaMemory = betaConstraints.createBetaMemory( config );
+
+        if ( indexedPositions.length > 0 ) {
+            TupleIndexHashTable tupleHashTable = (TupleIndexHashTable) betaMemory.getTupleMemory();
+            assertTrue( tupleHashTable.isIndexed() );
+            Index index = tupleHashTable.getIndex();
+
+            for ( int i = 0; i < indexedPositions.length; i++ ) {
+                checkSameConstraintForIndex( constraints[indexedPositions[i]],
+                                             index.getFieldIndex( i ) );
+            }
+
+            FactHandleIndexHashTable factHashTable = (FactHandleIndexHashTable) betaMemory.getFactHandleMemory();
+            assertTrue( factHashTable.isIndexed() );
+            index = factHashTable.getIndex();
+
+            for ( int i = 0; i < indexedPositions.length; i++ ) {
+                checkSameConstraintForIndex( constraints[indexedPositions[i]],
+                                             index.getFieldIndex( i ) );
+            }
+        } else {
+            TupleHashTable tupleHashTable = (TupleHashTable) betaMemory.getTupleMemory();
+            assertFalse( tupleHashTable.isIndexed() );
+
+            FactHashTable factHashTable = (FactHashTable) betaMemory.getFactHandleMemory();
+            assertFalse( factHashTable.isIndexed() );
+        }
+    }
+
+    protected void checkSameConstraintForIndex(VariableConstraint constraint,
+                                               FieldIndex fieldIndex) {
+        assertSame( constraint.getRequiredDeclarations()[0],
+                    fieldIndex.getDeclaration() );
+        assertSame( constraint.getEvaluator(),
+                    fieldIndex.getEvaluator() );
+        assertSame( constraint.getFieldExtractor(),
+                    fieldIndex.getExtractor() );
+    }
+
+    protected VariableConstraint[] convertToConstraints(LinkedList list) {
+        final VariableConstraint[] array = new VariableConstraint[list.size()];
+        int i = 0;
+        for ( LinkedListEntry entry = (LinkedListEntry) list.getFirst(); entry != null; entry = (LinkedListEntry) entry.getNext() ) {
+            array[i++] = (VariableConstraint) entry.getObject();
+        }
+        return array;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/DefaultBetaConstraintsTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/DefaultBetaConstraintsTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/DefaultBetaConstraintsTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,142 @@
+package org.drools.common;
+
+import org.drools.Cheese;
+import org.drools.base.evaluators.Operator;
+import org.drools.rule.VariableConstraint;
+
+public class DefaultBetaConstraintsTest extends BaseBetaConstraintsTest {
+    
+    public void testNoIndexConstraints() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.NOT_EQUAL, "type", Cheese.class );        
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0 };        
+        checkBetaConstraints( constraints, DefaultBetaConstraints.class );
+        
+        VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.NOT_EQUAL, "type", Cheese.class );        
+        constraints = new VariableConstraint[] { constraint0, constraint1 };        
+        checkBetaConstraints( constraints, DefaultBetaConstraints.class );        
+        
+        VariableConstraint constraint2 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );        
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint2 };        
+        checkBetaConstraints( constraints, DefaultBetaConstraints.class ); 
+        
+        VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.NOT_EQUAL, "type", Cheese.class );        
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3 };
+        checkBetaConstraints( constraints, DefaultBetaConstraints.class ); 
+        
+        VariableConstraint constraint4 = ( VariableConstraint ) getConstraint( "cheeseType4", Operator.NOT_EQUAL, "type", Cheese.class );        
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3, constraint4 }; 
+        checkBetaConstraints( constraints, DefaultBetaConstraints.class ); 
+        
+        VariableConstraint constraint5 = ( VariableConstraint ) getConstraint( "cheeseType5", Operator.NOT_EQUAL, "type", Cheese.class );        
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3,constraint5 };   
+        checkBetaConstraints( constraints, DefaultBetaConstraints.class );     
+        
+        VariableConstraint constraint6 = ( VariableConstraint ) getConstraint( "cheeseType6", Operator.NOT_EQUAL, "type", Cheese.class );        
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3, constraint4, constraint5, constraint6 };   
+        checkBetaConstraints( constraints, DefaultBetaConstraints.class );             
+    }    
+    
+    public void testIndexedConstraint() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.EQUAL, "type", Cheese.class );        
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0 };        
+        checkBetaConstraints( constraints, DefaultBetaConstraints.class );
+        
+        VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.EQUAL, "type", Cheese.class );        
+        constraints = new VariableConstraint[] { constraint0, constraint1 };        
+        checkBetaConstraints( constraints, DefaultBetaConstraints.class );        
+        
+        VariableConstraint constraint2 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.EQUAL, "type", Cheese.class );        
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint2 };        
+        checkBetaConstraints( constraints, DefaultBetaConstraints.class ); 
+        
+        VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.EQUAL, "type", Cheese.class );        
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3 };
+        checkBetaConstraints( constraints, DefaultBetaConstraints.class ); 
+        
+        VariableConstraint constraint4 = ( VariableConstraint ) getConstraint( "cheeseType4", Operator.EQUAL, "type", Cheese.class );        
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3, constraint4 }; 
+        checkBetaConstraints( constraints, DefaultBetaConstraints.class ); 
+        
+        VariableConstraint constraint5 = ( VariableConstraint ) getConstraint( "cheeseType5", Operator.EQUAL, "type", Cheese.class );        
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3, constraint4, constraint5 };   
+        checkBetaConstraints( constraints, DefaultBetaConstraints.class );     
+        
+        VariableConstraint constraint6 = ( VariableConstraint ) getConstraint( "cheeseType6", Operator.EQUAL, "type", Cheese.class );        
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3, constraint4, constraint5, constraint6 };   
+        checkBetaConstraints( constraints, DefaultBetaConstraints.class );          
+    }        
+    
+    
+    public void testSingleIndex() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint2 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType4", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint4 = ( VariableConstraint ) getConstraint( "cheeseType5", Operator.NOT_EQUAL, "type", Cheese.class );
+        
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3, constraint4 };
+        checkBetaConstraints( constraints, DefaultBetaConstraints.class );    
+    }   
+    
+    public void testSingleIndexNotFirst() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint2 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType4", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint4 = ( VariableConstraint ) getConstraint( "cheeseType5", Operator.EQUAL, "type", Cheese.class );
+        
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3, constraint4 };
+        
+        checkBetaConstraints( constraints, DefaultBetaConstraints.class );         
+    }    
+    
+    public void testDoubleIndex() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint2 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType4", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint4 = ( VariableConstraint ) getConstraint( "cheeseType5", Operator.NOT_EQUAL, "type", Cheese.class );
+        
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3, constraint4 };
+        
+        checkBetaConstraints( constraints, DefaultBetaConstraints.class );       
+    }   
+    
+    public void testDoubleIndexNotFirst() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint2 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType4", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint4 = ( VariableConstraint ) getConstraint( "cheeseType5", Operator.EQUAL, "type", Cheese.class );
+        
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3, constraint4 };
+        
+        checkBetaConstraints( constraints, DefaultBetaConstraints.class );       
+    }       
+    
+    
+    public void testTripleIndex() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint2 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType4", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint4 = ( VariableConstraint ) getConstraint( "cheeseType5", Operator.EQUAL, "type", Cheese.class );
+        
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3, constraint4 };
+        
+        checkBetaConstraints( constraints, DefaultBetaConstraints.class );               
+    }      
+    
+    public void testTripleIndexNotFirst() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint2 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType4", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint4 = ( VariableConstraint ) getConstraint( "cheeseType5", Operator.EQUAL, "type", Cheese.class );
+        
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3, constraint4 };
+        
+        checkBetaConstraints( constraints, DefaultBetaConstraints.class );               
+    }     
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/DoubleBetaConstraintsTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/DoubleBetaConstraintsTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/DoubleBetaConstraintsTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,35 @@
+package org.drools.common;
+
+import org.drools.Cheese;
+import org.drools.base.evaluators.Operator;
+import org.drools.rule.VariableConstraint;
+
+public class DoubleBetaConstraintsTest extends BaseBetaConstraintsTest {
+
+    public void testAllNoneIndxed() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1 };
+        checkBetaConstraints( constraints, DoubleBetaConstraints.class );
+    }   
+    
+    public void testOneIndxed() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1 };
+        checkBetaConstraints( constraints, DoubleBetaConstraints.class );
+        
+        constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.EQUAL, "type", Cheese.class );
+        constraints = new VariableConstraint[] { constraint0, constraint1 };
+        checkBetaConstraints( constraints, DoubleBetaConstraints.class );
+    }      
+    
+    public void testTwoIndxed() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1 };
+        checkBetaConstraints( constraints, DoubleBetaConstraints.class );
+    }
+    
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/EqualityKeyTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/EqualityKeyTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/EqualityKeyTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,47 @@
+package org.drools.common;
+
+import org.drools.Cheese;
+import org.drools.reteoo.ReteooFactHandleFactory;
+import org.drools.spi.FactHandleFactory;
+
+import junit.framework.TestCase;
+
+public class EqualityKeyTest extends TestCase {
+    public void test1() {
+        ReteooFactHandleFactory factory = new ReteooFactHandleFactory();
+        
+        InternalFactHandle ch1 = factory.newFactHandle( new Cheese ("c", 10), false, null );
+        EqualityKey key = new EqualityKey( ch1 );
+        
+        assertSame( ch1, key.getFactHandle() );
+        assertNull( key.getOtherFactHandle() );
+        
+        InternalFactHandle ch2 = factory.newFactHandle( new Cheese ("c", 10), false, null );
+        key.addFactHandle( ch2 );
+        
+        assertEquals( 1, key.getOtherFactHandle().size() );
+        assertEquals( ch2, key.getOtherFactHandle().get( 0 ) );
+        
+        key.removeFactHandle( ch1 );
+        assertSame( ch2, key.getFactHandle() );
+        assertNull( key.getOtherFactHandle() );
+        
+        key.removeFactHandle( ch2 );
+        assertNull( key.getFactHandle() );
+        assertNull( key.getOtherFactHandle() );         
+        
+        key = new EqualityKey( ch2 );
+        key.addFactHandle( ch1 );
+        assertSame( ch2, key.getFactHandle() );
+        assertEquals( 1, key.getOtherFactHandle().size() );
+        assertEquals( ch1, key.getOtherFactHandle().get( 0 ) );    
+        
+        key.removeFactHandle( ch1 );
+        assertSame( ch2, key.getFactHandle() );
+        assertNull( key.getOtherFactHandle() );
+        
+        key.removeFactHandle( ch2 );
+        assertNull( key.getFactHandle() );
+        assertNull( key.getOtherFactHandle() );        
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/QuadroupleBetaConstraintsTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/QuadroupleBetaConstraintsTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/QuadroupleBetaConstraintsTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,138 @@
+/**
+ * 
+ */
+package org.drools.common;
+
+import org.drools.Cheese;
+import org.drools.base.evaluators.Operator;
+import org.drools.rule.VariableConstraint;
+
+/**
+ * @author etirelli
+ *
+ */
+public class QuadroupleBetaConstraintsTest extends BaseBetaConstraintsTest {
+
+    public void testNoneIndxed() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint4 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1, constraint3, constraint4  };
+        checkBetaConstraints( constraints, QuadroupleBetaConstraints.class );
+    }   
+    
+    public void testOneIndxed() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint4 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1, constraint3, constraint4 };
+        checkBetaConstraints( constraints, QuadroupleBetaConstraints.class );
+        
+        constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.EQUAL, "type", Cheese.class );
+        constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint4 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint3, constraint4 };
+        checkBetaConstraints( constraints, QuadroupleBetaConstraints.class );  
+        
+        constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.EQUAL, "type", Cheese.class );
+        constraint4 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint3, constraint4 };
+        checkBetaConstraints( constraints, QuadroupleBetaConstraints.class );  
+        
+        constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint4 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.EQUAL, "type", Cheese.class );
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint3, constraint4 };
+        checkBetaConstraints( constraints, QuadroupleBetaConstraints.class );          
+    }   
+
+    public void testTwoIndxed() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint4 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1, constraint3, constraint4 };
+        checkBetaConstraints( constraints, QuadroupleBetaConstraints.class );
+        
+        constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.EQUAL, "type", Cheese.class );
+        constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.EQUAL, "type", Cheese.class );
+        constraint4 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint3, constraint4 };
+        checkBetaConstraints( constraints, QuadroupleBetaConstraints.class );  
+        
+        constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.EQUAL, "type", Cheese.class );
+        constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint4 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.EQUAL, "type", Cheese.class );
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint3, constraint4 };
+        checkBetaConstraints( constraints, QuadroupleBetaConstraints.class );  
+        
+        constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.EQUAL, "type", Cheese.class );
+        constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.EQUAL, "type", Cheese.class );
+        constraint4 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint3, constraint4 };
+        checkBetaConstraints( constraints, QuadroupleBetaConstraints.class );    
+        
+        constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.EQUAL, "type", Cheese.class );
+        constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint4 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.EQUAL, "type", Cheese.class );
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint3, constraint4 };
+        checkBetaConstraints( constraints, QuadroupleBetaConstraints.class );   
+        
+        constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.EQUAL, "type", Cheese.class );
+        constraint4 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.EQUAL, "type", Cheese.class );
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint3, constraint4 };
+        checkBetaConstraints( constraints, QuadroupleBetaConstraints.class );        
+    }    
+
+    public void testThreeIndxed() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint4 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1, constraint3, constraint4 };
+        checkBetaConstraints( constraints, QuadroupleBetaConstraints.class );
+        
+        constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.EQUAL, "type", Cheese.class );
+        constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.EQUAL, "type", Cheese.class );
+        constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint4 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.EQUAL, "type", Cheese.class );
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint3, constraint4 };
+        checkBetaConstraints( constraints, QuadroupleBetaConstraints.class );  
+        
+        constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.EQUAL, "type", Cheese.class );
+        constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.EQUAL, "type", Cheese.class );
+        constraint4 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.EQUAL, "type", Cheese.class );
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint3, constraint4 };
+        checkBetaConstraints( constraints, QuadroupleBetaConstraints.class );  
+        
+        constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.EQUAL, "type", Cheese.class );
+        constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.EQUAL, "type", Cheese.class );
+        constraint4 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.EQUAL, "type", Cheese.class );
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint3, constraint4 };
+        checkBetaConstraints( constraints, QuadroupleBetaConstraints.class );           
+    }      
+    
+    public void testFourIndxed() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint4 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1, constraint3, constraint4 };
+        checkBetaConstraints( constraints, QuadroupleBetaConstraints.class );         
+    }     
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/SequentialAgendaTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/SequentialAgendaTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/SequentialAgendaTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,42 @@
+package org.drools.common;
+
+import org.drools.rule.Rule;
+import org.drools.spi.Activation;
+
+import junit.framework.TestCase;
+
+public class SequentialAgendaTest extends TestCase {
+    public void testgetNext() {
+        SequentialAgendaGroupImpl agenda = new SequentialAgendaGroupImpl( "test", null );
+        
+        agenda.add( createActivation( 5 ) );
+        
+        agenda.add( createActivation( 49 ) );
+        
+        agenda.add( createActivation( 108 ) );
+        
+        agenda.add( createActivation( 320 ) );
+        
+        agenda.add( createActivation( 1053 ) );
+        
+        assertEquals( 5, agenda.getNext().getRule().getLoadOrder() );
+        assertEquals( 49, agenda.getNext().getRule().getLoadOrder() );
+        assertEquals( 108, agenda.getNext().getRule().getLoadOrder() );
+        assertEquals( 320, agenda.getNext().getRule().getLoadOrder() );
+        assertEquals( 1053, agenda.getNext().getRule().getLoadOrder() );
+        assertNull( agenda.getNext() );
+        
+    }
+    
+    public Activation createActivation(int index) {
+        Rule rule = new Rule( "test rule");
+        rule.setLoadOrder( index );
+        final AgendaItem item = new AgendaItem( 0,
+                                                null,
+                                                0,
+                                                null,
+                                                rule,
+                                                null );   
+        return item;
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/SingleBetaConstraintsTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/SingleBetaConstraintsTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/SingleBetaConstraintsTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,21 @@
+package org.drools.common;
+
+import org.drools.Cheese;
+import org.drools.base.evaluators.Operator;
+import org.drools.rule.VariableConstraint;
+
+public class SingleBetaConstraintsTest extends BaseBetaConstraintsTest {
+    
+    public void testIndxed() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0 };
+        checkBetaConstraints( constraints, SingleBetaConstraints.class );
+    }
+
+    public void testNotIndxed() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.NOT_EQUAL, "type", Cheese.class );                
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0 };
+        checkBetaConstraints( constraints, SingleBetaConstraints.class );
+    }    
+            
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/TripleBetaConstraintsTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/TripleBetaConstraintsTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/common/TripleBetaConstraintsTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,65 @@
+package org.drools.common;
+
+import org.drools.Cheese;
+import org.drools.base.evaluators.Operator;
+import org.drools.rule.VariableConstraint;
+
+public class TripleBetaConstraintsTest extends BaseBetaConstraintsTest {
+    
+
+    public void testNoneIndxed() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1, constraint3 };
+        checkBetaConstraints( constraints, TripleBetaConstraints.class );
+    }   
+    
+    public void testOneIndxed() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1, constraint3 };
+        checkBetaConstraints( constraints, TripleBetaConstraints.class );
+        
+        constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.EQUAL, "type", Cheese.class );
+        constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint3 };
+        checkBetaConstraints( constraints, TripleBetaConstraints.class );  
+        
+        constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.EQUAL, "type", Cheese.class );
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint3 };
+        checkBetaConstraints( constraints, TripleBetaConstraints.class );         
+    }   
+
+    public void testTwoIndxed() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1, constraint3 };
+        checkBetaConstraints( constraints, TripleBetaConstraints.class );
+        
+        constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.EQUAL, "type", Cheese.class );
+        constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.EQUAL, "type", Cheese.class );
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint3 };
+        checkBetaConstraints( constraints, TripleBetaConstraints.class );  
+        
+        constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.NOT_EQUAL, "type", Cheese.class );
+        constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.EQUAL, "type", Cheese.class );
+        constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.EQUAL, "type", Cheese.class );
+        constraints = new VariableConstraint[] { constraint0, constraint1, constraint3 };
+        checkBetaConstraints( constraints, TripleBetaConstraints.class );               
+    }    
+    
+    public void testThreeIndxed() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.EQUAL, "type", Cheese.class );
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1, constraint3 };
+        checkBetaConstraints( constraints, TripleBetaConstraints.class );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/event/AgendaEventSupportTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/event/AgendaEventSupportTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/event/AgendaEventSupportTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,213 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.drools.Cheese;
+import org.drools.FactHandle;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.base.ClassFieldExtractor;
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.ClassObjectType;
+import org.drools.base.FieldFactory;
+import org.drools.base.ShadowProxy;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.ComparableEvaluatorsDefinition;
+import org.drools.base.evaluators.EqualityEvaluatorsDefinition;
+import org.drools.base.evaluators.EvaluatorRegistry;
+import org.drools.base.evaluators.MatchesEvaluatorsDefinition;
+import org.drools.base.evaluators.Operator;
+import org.drools.base.evaluators.SetEvaluatorsDefinition;
+import org.drools.base.evaluators.SoundslikeEvaluatorsDefinition;
+import org.drools.rule.LiteralConstraint;
+import org.drools.rule.Package;
+import org.drools.rule.Pattern;
+import org.drools.rule.Rule;
+import org.drools.spi.Consequence;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldValue;
+import org.drools.spi.KnowledgeHelper;
+
+/**
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris</a>
+ */
+public class AgendaEventSupportTest extends TestCase {
+
+    public static EvaluatorRegistry registry = new EvaluatorRegistry();
+    static {
+        registry.addEvaluatorDefinition( new EqualityEvaluatorsDefinition() );
+        registry.addEvaluatorDefinition( new ComparableEvaluatorsDefinition() );
+        registry.addEvaluatorDefinition( new SetEvaluatorsDefinition() );
+        registry.addEvaluatorDefinition( new MatchesEvaluatorsDefinition() );
+        registry.addEvaluatorDefinition( new SoundslikeEvaluatorsDefinition() );
+    }
+
+    public void testIsSerializable() {
+        assertTrue( Serializable.class.isAssignableFrom( AgendaEventSupport.class ) );
+    }
+
+    public void testAgendaEventListener() throws Exception {
+        final RuleBase rb = RuleBaseFactory.newRuleBase();
+
+        // create a simpe package with one rule to test the events
+        final Package pkg = new Package( "org.drools.test" );
+        final Rule rule = new Rule( "test1" );
+        rule.setAgendaGroup( "test group" );
+        final ClassObjectType cheeseObjectType = new ClassObjectType( Cheese.class );
+        final Pattern pattern = new Pattern( 0,
+                                             cheeseObjectType );
+
+        final ClassFieldExtractor extractor = ClassFieldExtractorCache.getInstance().getExtractor( Cheese.class,
+                                                                                                   "type",
+                                                                                                   getClass().getClassLoader() );
+
+        final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
+
+        final Evaluator evaluator = registry.getEvaluator( ValueType.STRING_TYPE,
+                                                           Operator.EQUAL,
+                                                           null );
+
+        final LiteralConstraint constraint = new LiteralConstraint( extractor,
+                                                                    evaluator,
+                                                                    field );
+        pattern.addConstraint( constraint );
+        rule.addPattern( pattern );
+
+        rule.setConsequence( new Consequence() {
+            public void evaluate(final KnowledgeHelper knowledgeHelper,
+                                 final WorkingMemory workingMemory) throws Exception {
+            }
+        } );
+        pkg.addRule( rule );
+        rb.addPackage( pkg );
+
+        // create a new working memory and add an AgendaEventListener
+        final WorkingMemory wm = rb.newStatefulSession();
+        final List agendaList = new ArrayList();
+        final AgendaEventListener agendaEventListener = new AgendaEventListener() {
+
+            public void activationCancelled(ActivationCancelledEvent event,
+                                            WorkingMemory workingMemory) {
+                agendaList.add( event );
+
+            }
+
+            public void activationCreated(ActivationCreatedEvent event,
+                                          WorkingMemory workingMemory) {
+                agendaList.add( event );
+            }
+
+            public void afterActivationFired(AfterActivationFiredEvent event,
+                                             WorkingMemory workingMemory) {
+                agendaList.add( event );
+            }
+
+            public void agendaGroupPopped(AgendaGroupPoppedEvent event,
+                                          WorkingMemory workingMemory) {
+                agendaList.add( event );
+            }
+
+            public void agendaGroupPushed(AgendaGroupPushedEvent event,
+                                          WorkingMemory workingMemory) {
+                agendaList.add( event );
+            }
+
+            public void beforeActivationFired(BeforeActivationFiredEvent event,
+                                              WorkingMemory workingMemory) {
+                agendaList.add( event );
+            }
+        };
+        wm.addEventListener( agendaEventListener );
+
+        // assert the cheese fact
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           15 );
+        FactHandle cheddarHandle = wm.insert( cheddar );
+
+        // should be one ActivationCreatedEvent
+        assertEquals( 1,
+                      agendaList.size() );
+        ActivationCreatedEvent createdEvent = (ActivationCreatedEvent) agendaList.get( 0 );
+        assertSame( cheddar,
+                    unwrapShadow( createdEvent.getActivation().getTuple().get( 0 ).getObject() ) );
+        agendaList.clear();
+
+        // update results in a ActivationCancelledEvent and an ActivationCreatedEvent, note the object is always resolvable        
+        cheddar.setPrice( 14 );
+        wm.update( cheddarHandle,
+                   cheddar );
+        assertEquals( 2,
+                      agendaList.size() );
+        ActivationCancelledEvent cancelledEvent = (ActivationCancelledEvent) agendaList.get( 0 );
+        assertSame( cheddar,
+                    unwrapShadow( cancelledEvent.getActivation().getTuple().get( 0 ).getObject() ) );
+        createdEvent = (ActivationCreatedEvent) agendaList.get( 1 );
+        assertSame( cheddar,
+                    unwrapShadow( createdEvent.getActivation().getTuple().get( 0 ).getObject() ) );
+        agendaList.clear();
+
+        // retract results in a ActivationCancelledEvent, noe the object is not resolveable now as it no longer exists
+        wm.retract( cheddarHandle );
+        assertEquals( 1,
+                      agendaList.size() );
+        cancelledEvent = (ActivationCancelledEvent) agendaList.get( 0 );
+        assertNull( cancelledEvent.getActivation().getTuple().get( 0 ).getObject() );
+
+        // re-assert the fact so we can test the agenda group events
+        cheddarHandle = wm.insert( cheddar );
+        agendaList.clear();
+
+        // setFocus results in an AgendaGroupPushedEvent
+        wm.setFocus( "test group" );
+        assertEquals( 1,
+                      agendaList.size() );
+        final AgendaGroupPushedEvent pushedEvent = (AgendaGroupPushedEvent) agendaList.get( 0 );
+        assertEquals( "test group",
+                      pushedEvent.getAgendaGroup().getName() );
+        agendaList.clear();
+
+        // fireAllRules results in a BeforeActivationFiredEvent and an AfterActivationFiredEvent
+        // the AgendaGroup becomes empty, which results in a popped event.
+        wm.fireAllRules();
+        assertEquals( 3,
+                      agendaList.size() );
+        final BeforeActivationFiredEvent beforeEvent = (BeforeActivationFiredEvent) agendaList.get( 0 );
+        assertSame( cheddar,
+                    unwrapShadow( beforeEvent.getActivation().getTuple().get( 0 ).getObject() ) );
+        final AfterActivationFiredEvent afterEvent = (AfterActivationFiredEvent) agendaList.get( 1 );
+        assertSame( cheddar,
+                    unwrapShadow( afterEvent.getActivation().getTuple().get( 0 ).getObject() ) );
+        final AgendaGroupPoppedEvent poppedEvent = (AgendaGroupPoppedEvent) agendaList.get( 2 );
+        assertEquals( "test group",
+                      poppedEvent.getAgendaGroup().getName() );
+    }
+
+    private Object unwrapShadow(Object object) {
+        if ( object instanceof ShadowProxy ) {
+            return ((ShadowProxy) object).getShadowedObject();
+        } else {
+            return object;
+        }
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/event/RuleBaseEventListenerTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/event/RuleBaseEventListenerTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/event/RuleBaseEventListenerTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,332 @@
+/*
+ * Copyright 2007 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.
+ *
+ * Created on Sep 11, 2007
+ */
+package org.drools.event;
+
+import junit.framework.TestCase;
+
+import org.drools.Cheese;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.base.ClassFieldExtractor;
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.ClassObjectType;
+import org.drools.base.FieldFactory;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.EqualityEvaluatorsDefinition;
+import org.drools.base.evaluators.Operator;
+import org.drools.rule.LiteralConstraint;
+import org.drools.rule.Package;
+import org.drools.rule.Pattern;
+import org.drools.rule.Rule;
+import org.drools.spi.Consequence;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldValue;
+import org.drools.spi.KnowledgeHelper;
+
+/**
+ * @author etirelli
+ *
+ */
+public class RuleBaseEventListenerTest extends TestCase {
+
+    private RuleBase             ruleBase;
+    private TestRuleBaseListener listener1;
+    private TestRuleBaseListener listener2;
+    private Package              pkg;
+
+    /* (non-Javadoc)
+     * @see junit.framework.TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        ruleBase = RuleBaseFactory.newRuleBase();
+        listener1 = new TestRuleBaseListener( "(listener-1) " );
+        listener2 = new TestRuleBaseListener( "(listener-2) " );
+        ruleBase.addEventListener( listener1 );
+        ruleBase.addEventListener( listener2 );
+
+        final Rule rule1 = new Rule( "test1" );
+        final ClassObjectType cheeseObjectType = new ClassObjectType( Cheese.class );
+        final Pattern pattern = new Pattern( 0,
+                                             cheeseObjectType );
+
+        final ClassFieldExtractor extractor = ClassFieldExtractorCache.getInstance().getExtractor( Cheese.class,
+                                                                                                   "type",
+                                                                                                   getClass().getClassLoader() );
+
+        final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
+
+        final Evaluator evaluator = new EqualityEvaluatorsDefinition().getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL, null );
+
+        final LiteralConstraint constraint = new LiteralConstraint( extractor,
+                                                                    evaluator,
+                                                                    field );
+        pattern.addConstraint( constraint );
+        rule1.addPattern( pattern );
+
+        rule1.setConsequence( new Consequence() {
+            private static final long serialVersionUID = 1L;
+
+            public void evaluate(final KnowledgeHelper knowledgeHelper,
+                                 final WorkingMemory workingMemory) throws Exception {
+            }
+        } );
+
+        final Rule rule2 = new Rule( "test2" );
+        final ClassObjectType cheeseObjectType2 = new ClassObjectType( Cheese.class );
+        final Pattern pattern2 = new Pattern( 0,
+                                              cheeseObjectType2 );
+
+        final FieldValue field2 = FieldFactory.getFieldValue( "stilton" );
+
+        final LiteralConstraint constraint2 = new LiteralConstraint( extractor,
+                                                                     evaluator,
+                                                                     field2 );
+        pattern2.addConstraint( constraint2 );
+        rule2.addPattern( pattern2 );
+
+        rule2.setConsequence( new Consequence() {
+            private static final long serialVersionUID = 1L;
+
+            public void evaluate(final KnowledgeHelper knowledgeHelper,
+                                 final WorkingMemory workingMemory) throws Exception {
+            }
+        } );
+
+        pkg = new Package( "org.drools.test1" );
+        pkg.addRule( rule1 );
+        pkg.addRule( rule2 );
+
+    }
+
+    /* (non-Javadoc)
+     * @see junit.framework.TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    public void testAddPackageEvents() throws Exception {
+        assertEquals( 0,
+                      listener1.getBeforePackageAdded() );
+        assertEquals( 0,
+                      listener1.getAfterPackageAdded() );
+        assertEquals( 0,
+                      listener2.getBeforePackageAdded() );
+        assertEquals( 0,
+                      listener2.getAfterPackageAdded() );
+        assertEquals( 0,
+                      listener1.getBeforeRuleAdded() );
+        assertEquals( 0,
+                      listener1.getAfterRuleAdded() );
+        assertEquals( 0,
+                      listener2.getBeforeRuleAdded() );
+        assertEquals( 0,
+                      listener2.getAfterRuleAdded() );
+
+        this.ruleBase.addPackage( pkg );
+
+        assertEquals( 1,
+                      listener1.getBeforePackageAdded() );
+        assertEquals( 1,
+                      listener1.getAfterPackageAdded() );
+        assertEquals( 1,
+                      listener2.getBeforePackageAdded() );
+        assertEquals( 1,
+                      listener2.getAfterPackageAdded() );
+        assertEquals( 2,
+                      listener1.getBeforeRuleAdded() );
+        assertEquals( 2,
+                      listener1.getAfterRuleAdded() );
+        assertEquals( 2,
+                      listener2.getBeforeRuleAdded() );
+        assertEquals( 2,
+                      listener2.getAfterRuleAdded() );
+    }
+
+    public void testRemovePackageEvents() throws Exception {
+        this.ruleBase.addPackage( pkg );
+
+        assertEquals( 0,
+                      listener1.getBeforePackageRemoved() );
+        assertEquals( 0,
+                      listener1.getAfterPackageRemoved() );
+        assertEquals( 0,
+                      listener2.getBeforePackageRemoved() );
+        assertEquals( 0,
+                      listener2.getAfterPackageRemoved() );
+
+        assertEquals( 0,
+                      listener1.getBeforeRuleRemoved() );
+        assertEquals( 0,
+                      listener1.getAfterRuleRemoved() );
+        assertEquals( 0,
+                      listener2.getBeforeRuleRemoved() );
+        assertEquals( 0,
+                      listener2.getAfterRuleRemoved() );
+
+        this.ruleBase.removePackage( "org.drools.test1" );
+
+        assertEquals( 1,
+                      listener1.getBeforePackageRemoved() );
+        assertEquals( 1,
+                      listener1.getAfterPackageRemoved() );
+        assertEquals( 1,
+                      listener2.getBeforePackageRemoved() );
+        assertEquals( 1,
+                      listener2.getAfterPackageRemoved() );
+        assertEquals( 2,
+                      listener1.getBeforeRuleRemoved() );
+        assertEquals( 2,
+                      listener1.getAfterRuleRemoved() );
+        assertEquals( 2,
+                      listener2.getBeforeRuleRemoved() );
+        assertEquals( 2,
+                      listener2.getAfterRuleRemoved() );
+
+    }
+
+    public static class TestRuleBaseListener
+        implements
+        RuleBaseEventListener {
+        private String id;
+        private int    beforePackageAdded   = 0;
+        private int    afterPackageAdded    = 0;
+        private int    beforePackageRemoved = 0;
+        private int    afterPackageRemoved  = 0;
+        private int    beforeRuleAdded      = 0;
+        private int    afterRuleAdded       = 0;
+        private int    beforeRuleRemoved    = 0;
+        private int    afterRuleRemoved     = 0;
+
+        public TestRuleBaseListener(String id) {
+            super();
+            this.id = id;
+        }
+
+        public void afterPackageAdded(AfterPackageAddedEvent event) {
+            //            System.out.println( this.id + event );
+            this.afterPackageAdded++;
+        }
+
+        public void beforePackageAdded(BeforePackageAddedEvent event) {
+            //            System.out.println( this.id + event );
+            this.beforePackageAdded++;
+        }
+
+        protected int getAfterPackageAdded() {
+            return afterPackageAdded;
+        }
+
+        protected int getBeforePackageAdded() {
+            return beforePackageAdded;
+        }
+
+        protected String getId() {
+            return id;
+        }
+
+        public void afterPackageRemoved(AfterPackageRemovedEvent event) {
+            //            System.out.println( this.id + event );
+            this.afterPackageRemoved++;
+        }
+
+        public void beforePackageRemoved(BeforePackageRemovedEvent event) {
+            //            System.out.println( this.id + event );
+            this.beforePackageRemoved++;
+        }
+
+        protected int getAfterPackageRemoved() {
+            return afterPackageRemoved;
+        }
+
+        protected int getBeforePackageRemoved() {
+            return beforePackageRemoved;
+        }
+
+        public int getAfterRuleAdded() {
+            return afterRuleAdded;
+        }
+
+        public int getBeforeRuleAdded() {
+            return beforeRuleAdded;
+        }
+
+        public void afterRuleAdded(AfterRuleAddedEvent event) {
+            //            System.out.println( this.id + event );
+            this.afterRuleAdded++;
+        }
+
+        public void beforeRuleAdded(BeforeRuleAddedEvent event) {
+            //            System.out.println( this.id + event );
+            this.beforeRuleAdded++;
+        }
+
+        public int getAfterRuleRemoved() {
+            return afterRuleRemoved;
+        }
+
+        public int getBeforeRuleRemoved() {
+            return beforeRuleRemoved;
+        }
+
+        public void afterRuleRemoved(AfterRuleRemovedEvent event) {
+            //            System.out.println( this.id + event );
+            this.afterRuleRemoved++;
+        }
+
+        public void beforeRuleRemoved(BeforeRuleRemovedEvent event) {
+            //            System.out.println( this.id + event );
+            this.beforeRuleRemoved++;
+        }
+
+        public void afterFunctionRemoved(AfterFunctionRemovedEvent event) {
+            // TODO Auto-generated method stub
+            
+        }
+
+        public void afterRuleBaseLocked(AfterRuleBaseLockedEvent event) {
+            // TODO Auto-generated method stub
+            
+        }
+
+        public void afterRuleBaseUnlocked(AfterRuleBaseUnlockedEvent event) {
+            // TODO Auto-generated method stub
+            
+        }
+
+        public void beforeFunctionRemoved(BeforeFunctionRemovedEvent event) {
+            // TODO Auto-generated method stub
+            
+        }
+
+        public void beforeRuleBaseLocked(BeforeRuleBaseLockedEvent event) {
+            // TODO Auto-generated method stub
+            
+        }
+
+        public void beforeRuleBaseUnlocked(BeforeRuleBaseUnlockedEvent event) {
+            // TODO Auto-generated method stub
+            
+        }
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/event/WorkingMemoryEventSupportTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/event/WorkingMemoryEventSupportTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/event/WorkingMemoryEventSupportTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,86 @@
+package org.drools.event;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.Cheese;
+import org.drools.FactHandle;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+
+import junit.framework.TestCase;
+
+/**
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris</a>
+ */
+public class WorkingMemoryEventSupportTest extends TestCase {
+    public void testIsSerializable() {
+        assertTrue( Serializable.class.isAssignableFrom( WorkingMemoryEventSupport.class ) );
+    }
+
+    public void testWorkingMemoryEventListener() {
+        final RuleBase rb = RuleBaseFactory.newRuleBase();
+        final WorkingMemory wm = rb.newStatefulSession();
+
+        final List wmList = new ArrayList();
+        final WorkingMemoryEventListener workingMemoryListener = new WorkingMemoryEventListener() {
+
+            public void objectInserted(ObjectInsertedEvent event) {
+                wmList.add( event );
+            }
+
+            public void objectUpdated(ObjectUpdatedEvent event) {
+                wmList.add( event );
+            }
+
+            public void objectRetracted(ObjectRetractedEvent event) {
+                wmList.add( event );
+            }
+
+        };
+
+        wm.addEventListener( workingMemoryListener );
+
+        final Cheese stilton = new Cheese( "stilton",
+                                     15 );
+        final Cheese cheddar = new Cheese( "cheddar",
+                                     17 );
+
+        final FactHandle stiltonHandle = wm.insert( stilton );
+
+        final ObjectInsertedEvent oae = (ObjectInsertedEvent) wmList.get( 0 );
+        assertSame( stiltonHandle,
+                    oae.getFactHandle() );
+
+        wm.update( stiltonHandle,
+                         stilton );
+        final ObjectUpdatedEvent ome = (ObjectUpdatedEvent) wmList.get( 1 );
+        assertSame( stiltonHandle,
+                    ome.getFactHandle() );
+
+        wm.retract( stiltonHandle );
+        final ObjectRetractedEvent ore = (ObjectRetractedEvent) wmList.get( 2 );
+        assertSame( stiltonHandle,
+                    ore.getFactHandle() );
+
+        wm.insert( cheddar );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/BaseMannersTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/BaseMannersTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/BaseMannersTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,1173 @@
+package org.drools.examples.manners;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.StringTokenizer;
+
+import junit.framework.TestCase;
+
+import org.drools.WorkingMemory;
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.ClassObjectType;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.EqualityEvaluatorsDefinition;
+import org.drools.base.evaluators.Operator;
+import org.drools.base.field.BooleanFieldImpl;
+import org.drools.base.field.LongFieldImpl;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.Declaration;
+import org.drools.rule.GroupElement;
+import org.drools.rule.GroupElementFactory;
+import org.drools.rule.InvalidRuleException;
+import org.drools.rule.LiteralConstraint;
+import org.drools.rule.Package;
+import org.drools.rule.Pattern;
+import org.drools.rule.Rule;
+import org.drools.rule.VariableConstraint;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.spi.Consequence;
+import org.drools.spi.ConsequenceException;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.FieldValue;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.Tuple;
+
+public abstract class BaseMannersTest extends TestCase {
+    /** Number of guests at the dinner (default: 16). */
+    private final int       numGuests  = 16;
+
+    /** Number of seats at the table (default: 16). */
+    private final int       numSeats   = 16;
+
+    /** Minimum number of hobbies each guest should have (default: 2). */
+    private final int       minHobbies = 2;
+
+    /** Maximun number of hobbies each guest should have (default: 3). */
+    private final int       maxHobbies = 3;
+
+    protected Package       pkg;
+
+    private ClassObjectType contextType;
+    private ClassObjectType guestType;
+    private ClassObjectType seatingType;
+    private ClassObjectType lastSeatType;
+    private ClassObjectType countType;
+    private ClassObjectType pathType;
+    private ClassObjectType chosenType;
+    private Evaluator       objectEqualEvaluator;
+    private Evaluator       objectNotEqualEvaluator;
+    private Evaluator       integerEqualEvaluator;
+    //private Evaluator       integerNotEqualEvaluator;
+    private Evaluator       booleanEqualEvaluator;
+
+    //private Evaluator       booleanNotEqualEvaluator;
+
+    protected void setUp() throws Exception {
+        //Class shadow = ShadowProxyFactory.getProxy( Context.class );
+        this.contextType = new ClassObjectType( Context.class );
+
+        //shadow = ShadowProxyFactory.getProxy( Guest.class );
+        this.guestType = new ClassObjectType( Guest.class );
+
+        //shadow = ShadowProxyFactory.getProxy( Seating.class );
+        this.seatingType = new ClassObjectType( Seating.class );
+
+        //shadow = ShadowProxyFactory.getProxy( LastSeat.class );
+        this.lastSeatType = new ClassObjectType( LastSeat.class );
+
+        //shadow = ShadowProxyFactory.getProxy( Count.class );
+        this.countType = new ClassObjectType( Count.class );
+
+        //shadow = ShadowProxyFactory.getProxy( Path.class );
+        this.pathType = new ClassObjectType( Path.class );
+
+        //shadow = ShadowProxyFactory.getProxy( Chosen.class );
+        this.chosenType = new ClassObjectType( Chosen.class );
+
+        EqualityEvaluatorsDefinition evals = new EqualityEvaluatorsDefinition();
+        this.integerEqualEvaluator = evals.getEvaluator( ValueType.PINTEGER_TYPE, Operator.EQUAL, null );
+        this.objectEqualEvaluator = evals.getEvaluator( ValueType.OBJECT_TYPE, Operator.EQUAL, null );
+        this.objectNotEqualEvaluator = evals.getEvaluator( ValueType.OBJECT_TYPE, Operator.NOT_EQUAL, null );
+        this.booleanEqualEvaluator = evals.getEvaluator( ValueType.PBOOLEAN_TYPE, Operator.EQUAL, null );
+
+        this.pkg = new Package( "org.drools.examples.manners" );
+        this.pkg.addRule( getAssignFirstSeatRule() );
+        this.pkg.addRule( getFindSeating() );
+        this.pkg.addRule( getPathDone() );
+        this.pkg.addRule( getMakePath() );
+        this.pkg.addRule( getContinueProcessing() );
+        this.pkg.addRule( getAreWeDone() );
+        this.pkg.addRule( getAllDone() );
+
+    }
+
+    /**
+     * <pre>
+     *    rule assignFirstSeat() {
+     *        Context context;
+     *        Guest guest;
+     *        Count count;
+     *        when {
+     *            context : Context( state == Context.START_UP )
+     *            guest : Guest()
+     *            count : Count()
+     *        } then {
+     *            String guestName = guest.getName();
+     *            drools.assert( new Seating( count.getValue(), 1, true, 1, guestName, 1, guestName) );
+     *            drools.assert( new Path( count.getValue(), 1, guestName ) );
+     *            count.setCount(  count.getValue() + 1 );
+     *   
+     *            System.err.println( &quot;seat 1 &quot; + guest.getName() + &quot; );
+     *   
+     *            context.setPath( Context.ASSIGN_SEATS );
+     *        }
+     *    } 
+     * </pre>
+     * 
+     * 
+     * @return
+     * @throws IntrospectionException
+     * @throws InvalidRuleException
+     */
+    private Rule getAssignFirstSeatRule() throws IntrospectionException,
+                                         InvalidRuleException {
+        final Rule rule = new Rule( "assignFirstSeat" );
+
+        // -----------
+        // context : Context( state == Context.START_UP )
+        // -----------
+        final Pattern contextPattern = new Pattern( 0,
+                                                    this.contextType,
+                                                    "context" );
+
+        contextPattern.addConstraint( getLiteralConstraint( contextPattern,
+                                                            "state",
+                                                            Context.START_UP,
+                                                            this.integerEqualEvaluator ) );
+
+        rule.addPattern( contextPattern );
+
+        final Declaration contextDeclaration = rule.getDeclaration( "context" );
+
+        // -----------
+        // guest: Guest()
+        // -----------
+        final Pattern guestPattern = new Pattern( 1,
+                                                  this.guestType,
+                                                  "guest" );
+
+        rule.addPattern( guestPattern );
+
+        final Declaration guestDeclaration = rule.getDeclaration( "guest" );
+
+        // ------------
+        // count : Count()
+        // ------------
+        final Pattern countPattern = new Pattern( 2,
+                                                  this.countType,
+                                                  "count" );
+
+        rule.addPattern( countPattern );
+
+        final Declaration countDeclaration = rule.getDeclaration( "count" );
+
+        final Consequence consequence = new Consequence() {
+
+            public void evaluate(KnowledgeHelper drools,
+                                 WorkingMemory workingMemory) throws ConsequenceException {
+                try {
+                    Rule rule = drools.getRule();
+                    Tuple tuple = drools.getTuple();
+
+                    Guest guest = (Guest) drools.get( guestDeclaration );
+                    Context context = (Context) drools.get( contextDeclaration );
+                    Count count = (Count) drools.get( countDeclaration );
+
+                    String guestName = guest.getName();
+
+                    Seating seating = new Seating( count.getValue(),
+                                                   0,
+                                                   true,
+                                                   1,
+                                                   guestName,
+                                                   1,
+                                                   guestName );
+
+                    drools.insert( seating );
+
+                    Path path = new Path( count.getValue(),
+                                          1,
+                                          guestName );
+
+                    drools.insert( path );
+
+                    count.setValue( count.getValue() );
+                    drools.update( tuple.get( countDeclaration ),
+                                   count );
+
+                    drools.modifyRetract( context );;
+                    context.setState( Context.ASSIGN_SEATS );
+//                    drools.update( tuple.get( contextDeclaration ),
+//                            context );
+                    
+                    drools.modifyInsert( context );
+
+                    System.err.println( "assign first seat :  " + seating + " : " + path );
+
+                } catch ( Exception e ) {
+                    e.printStackTrace();
+                    throw new ConsequenceException( e );
+                }
+            }
+
+        };
+
+        rule.setConsequence( consequence );
+
+        return rule;
+    }
+
+    /**
+     * <pre>
+     *    rule findSeating() {
+     *       Context context;
+     *       int seatingId, seatingPid;
+     *       String seatingRightGuestName, leftGuestName;
+     *       Sex rightGuestSex;
+     *       Hobby rightGuestHobby;
+     *       Count count;
+     *       
+     *       when {
+     *           context : Context( state == Context.ASSIGN_SEATS )
+     *           Seating( seatingId:id, seatingPid:pid, pathDone == true 
+     *                    seatingRightSeat:rightSeat seatingRightGuestName:rightGuestName )
+     *           Guest( name == seatingRightGuestName, rightGuestSex:sex, rightGuestHobby:hobby )
+     *           Guest( leftGuestName:name , sex != rightGuestSex, hobby == rightGuestHobby )
+     *    
+     *           count : Count()
+     *    
+     *           not ( Path( id == seatingId, guestName == leftGuestName) )
+     *           not ( Chosen( id == seatingId, guestName == leftGuestName, hobby == rightGuestHobby) )
+     *       } then {
+     *           int newSeat = rightSeat + 1;
+     *           drools.assert( new Seating( coung.getValue(), rightSeat, rightSeatName, leftGuestName, newSeat, countValue, id, false );
+     *           drools.assert( new Path( countValue, leftGuestName, newSeat );
+     *           drools.assert( new Chosen( id, leftGuestName, rightGuestHobby ) );
+     *    
+     *           System.err.println( &quot;seat &quot; + rightSeat + &quot; &quot; + rightSeatName + &quot; &quot; + leftGuestName );
+     *    
+     *           count.setCount(  countValue + 1 );
+     *           context.setPath( Context.MAKE_PATH );
+     *       }
+     *    } 
+     * </pre>
+     * 
+     * @return
+     * @throws IntrospectionException
+     * @throws InvalidRuleException
+     */
+    private Rule getFindSeating() throws IntrospectionException,
+                                 InvalidRuleException {
+        final Rule rule = new Rule( "findSeating" );
+
+        // ---------------
+        // context : Context( state == Context.ASSIGN_SEATS )
+        // ---------------
+        final Pattern contextPattern = new Pattern( 0,
+                                                    this.contextType,
+                                                    "context" );
+
+        contextPattern.addConstraint( getLiteralConstraint( contextPattern,
+                                                            "state",
+                                                            Context.ASSIGN_SEATS,
+                                                            this.integerEqualEvaluator ) );
+
+        rule.addPattern( contextPattern );
+
+        final Declaration contextDeclaration = rule.getDeclaration( "context" );
+
+        // -------------------------------
+        // Seating( seatingId:id, seatingPid:pid, pathDone == true
+        // seatingRightSeat:rightSeat seatingRightGuestName:rightGuestName )
+        // -------------------------------
+        final Pattern seatingPattern = new Pattern( 1,
+                                                    this.seatingType );
+
+        setFieldDeclaration( seatingPattern,
+                             "id",
+                             "seatingId" );
+
+        setFieldDeclaration( seatingPattern,
+                             "pid",
+                             "seatingPid" );
+
+        seatingPattern.addConstraint( getLiteralConstraint( seatingPattern,
+                                                            "pathDone",
+                                                            true,
+                                                            this.booleanEqualEvaluator ) );
+
+        setFieldDeclaration( seatingPattern,
+                             "rightSeat",
+                             "seatingRightSeat" );
+
+        setFieldDeclaration( seatingPattern,
+                             "rightGuestName",
+                             "seatingRightGuestName" );
+
+        rule.addPattern( seatingPattern );
+
+        final Declaration seatingIdDeclaration = rule.getDeclaration( "seatingId" );
+        final Declaration seatingPidDeclaration = rule.getDeclaration( "seatingPid" );
+        final Declaration seatingRightGuestNameDeclaration = rule.getDeclaration( "seatingRightGuestName" );
+        final Declaration seatingRightSeatDeclaration = rule.getDeclaration( "seatingRightSeat" );
+        // --------------
+        // Guest( name == seatingRightGuestName, rightGuestSex:sex,
+        // rightGuestHobby:hobby )
+        // ---------------
+        final Pattern rightGuestPattern = new Pattern( 2,
+                                                       this.guestType );
+
+        rightGuestPattern.addConstraint( getBoundVariableConstraint( rightGuestPattern,
+                                                                     "name",
+                                                                     seatingRightGuestNameDeclaration,
+                                                                     this.objectEqualEvaluator ) );
+
+        setFieldDeclaration( rightGuestPattern,
+                             "sex",
+                             "rightGuestSex" );
+
+        setFieldDeclaration( rightGuestPattern,
+                             "hobby",
+                             "rightGuestHobby" );
+
+        rule.addPattern( rightGuestPattern );
+
+        final Declaration rightGuestSexDeclaration = rule.getDeclaration( "rightGuestSex" );
+        final Declaration rightGuestHobbyDeclaration = rule.getDeclaration( "rightGuestHobby" );
+
+        // ----------------
+        // Guest( leftGuestName:name , sex != rightGuestSex, hobby ==
+        // rightGuestHobby )
+        // ----------------
+        final Pattern leftGuestPattern = new Pattern( 3,
+                                                      this.guestType );
+
+        setFieldDeclaration( leftGuestPattern,
+                             "name",
+                             "leftGuestName" );
+
+        leftGuestPattern.addConstraint( getBoundVariableConstraint( rightGuestPattern,
+                                                                    "hobby",
+                                                                    rightGuestHobbyDeclaration,
+                                                                    this.objectEqualEvaluator ) );
+
+        leftGuestPattern.addConstraint( getBoundVariableConstraint( leftGuestPattern,
+                                                                    "sex",
+                                                                    rightGuestSexDeclaration,
+                                                                    this.objectNotEqualEvaluator ) );
+
+        rule.addPattern( leftGuestPattern );
+        final Declaration leftGuestNameDeclaration = rule.getDeclaration( "leftGuestName" );
+
+        // ---------------
+        // count : Count()
+        // ---------------
+        final Pattern count = new Pattern( 4,
+                                           this.countType,
+                                           "count" );
+
+        rule.addPattern( count );
+
+        final Declaration countDeclaration = rule.getDeclaration( "count" );
+
+        // --------------
+        // not ( Path( id == seatingId, guestName == leftGuestName) )
+        // --------------
+        final Pattern notPathPattern = new Pattern( 5,
+                                                    this.pathType );
+
+        notPathPattern.addConstraint( getBoundVariableConstraint( notPathPattern,
+                                                                  "id",
+                                                                  seatingIdDeclaration,
+                                                                  this.integerEqualEvaluator ) );
+
+        notPathPattern.addConstraint( getBoundVariableConstraint( notPathPattern,
+                                                                  "guestName",
+                                                                  leftGuestNameDeclaration,
+                                                                  this.objectEqualEvaluator ) );
+        final GroupElement notPath = GroupElementFactory.newNotInstance();
+        notPath.addChild( notPathPattern );
+        rule.addPattern( notPath );
+        // ------------
+        // not ( Chosen( id == seatingId, guestName == leftGuestName, hobby ==
+        // rightGuestHobby ) )
+        // ------------
+        final Pattern notChosenPattern = new Pattern( 6,
+                                                      this.chosenType );
+
+        notChosenPattern.addConstraint( getBoundVariableConstraint( notChosenPattern,
+                                                                    "id",
+                                                                    seatingIdDeclaration,
+                                                                    this.integerEqualEvaluator ) );
+
+        notChosenPattern.addConstraint( getBoundVariableConstraint( notChosenPattern,
+                                                                    "guestName",
+                                                                    leftGuestNameDeclaration,
+                                                                    this.objectEqualEvaluator ) );
+
+        notChosenPattern.addConstraint( getBoundVariableConstraint( notChosenPattern,
+                                                                    "hobby",
+                                                                    rightGuestHobbyDeclaration,
+                                                                    this.objectEqualEvaluator ) );
+
+        final GroupElement notChosen = GroupElementFactory.newNotInstance();
+        notChosen.addChild( notChosenPattern );
+
+        rule.addPattern( notChosen );
+
+        // ------------
+        // int newSeat = rightSeat + 1;
+        // drools.assert( new Seating( coung.getValue(), rightSeat,
+        // rightSeatName, leftGuestName, newSeat, countValue, id, false );
+        // drools.assert( new Path( countValue, leftGuestName, newSeat );
+        // drools.assert( new Chosen( id, leftGuestName, rightGuestHobby ) );
+        // 
+        // System.err.println( "seat " + rightSeat + " " + rightSeatName + " " +
+        // leftGuestName );
+        //
+        // count.setCount( countValue + 1 );
+        // context.setPath( Context.MAKE_PATH );
+        // ------------
+        final Consequence consequence = new Consequence() {
+
+            public void evaluate(KnowledgeHelper drools,
+                                 WorkingMemory workingMemory) throws ConsequenceException {
+                try {
+                    //                    MemoryVisitor visitor = new MemoryVisitor( ( InternalWorkingMemory ) workingMemory );
+                    //                    visitor.visit( workingMemory.getRuleBase() );
+
+                    Rule rule = drools.getRule();
+                    Tuple tuple = drools.getTuple();
+
+                    Context context = (Context) drools.get( contextDeclaration );
+                    Count count = (Count) drools.get( countDeclaration );
+                    int seatId = seatingIdDeclaration.getExtractor().getIntValue( (InternalWorkingMemory) workingMemory,
+                                                                                  tuple.get( seatingIdDeclaration ).getObject() );
+                    int seatingRightSeat = seatingRightSeatDeclaration.getExtractor().getIntValue( (InternalWorkingMemory) workingMemory,
+                                                                                                   tuple.get( seatingRightSeatDeclaration ).getObject() );
+
+                    String leftGuestName = (String) drools.get( leftGuestNameDeclaration );
+                    String rightGuestName = (String) drools.get( seatingRightGuestNameDeclaration );
+                    Hobby rightGuestHobby = (Hobby) drools.get( rightGuestHobbyDeclaration );
+
+                    Seating seating = new Seating( count.getValue(),
+                                                   seatId,
+                                                   false,
+                                                   seatingRightSeat,
+                                                   rightGuestName,
+                                                   seatingRightSeat + 1,
+                                                   leftGuestName );
+                    drools.insert( seating );
+
+                    Path path = new Path( count.getValue(),
+                                          seatingRightSeat + 1,
+                                          leftGuestName );
+
+                    drools.insert( path );
+
+                    Chosen chosen = new Chosen( seatId,
+                                                leftGuestName,
+                                                rightGuestHobby );
+
+                    drools.insert( chosen );
+                    count.setValue( count.getValue() + 1 );
+
+                    //                    if ( count.getValue() == 5 ) {
+                    //                        drools.retractObject( tuple.getFactHandleForDeclaration( countDeclaration ) );
+                    //                    } else {
+                    //                        drools.update( tuple.getFactHandleForDeclaration( countDeclaration ),
+                    //                                             count );                        
+                    //                    }
+
+                    drools.update( tuple.get( countDeclaration ),
+                                   count );
+
+                    context.setState( Context.MAKE_PATH );
+                    drools.update( tuple.get( contextDeclaration ),
+                                   context );
+
+                    System.err.println( "find seating : " + seating + " : " + path + " : " + chosen );
+
+                } catch ( Exception e ) {
+                    e.printStackTrace();
+                    throw new ConsequenceException( e );
+                }
+            }
+        };
+
+        rule.setConsequence( consequence );
+
+        return rule;
+    }
+
+    /**
+     * <pre>
+     *    rule makePath() {
+     *        Context context;
+     *        int seatingId, seatingPid, pathSeat;
+     *        String pathGuestName;
+     *   
+     *        when {
+     *            Context( state == Context.MAKE_PATH )
+     *            Seating( seatingId:id, seatingPid:pid, pathDone == false )
+     *            Path( id == seatingPid, pathGuestName:guest, pathSeat:seat )
+     *            (not Path( id == seatingId, guestName == pathGuestName )
+     *        } else {
+     *            drools.assert( new Path( seatingId, pathSeat, pathGuestName ) );
+     *   
+     *        }
+     *    } 
+     * </pre>
+     * 
+     * @return
+     * @throws IntrospectionException
+     * @throws InvalidRuleException
+     */
+    private Rule getMakePath() throws IntrospectionException,
+                              InvalidRuleException {
+        final Rule rule = new Rule( "makePath" );
+
+        // -----------
+        // context : Context( state == Context.MAKE_PATH )
+        // -----------
+        final Pattern contextPattern = new Pattern( 0,
+                                                    this.contextType );
+
+        contextPattern.addConstraint( getLiteralConstraint( contextPattern,
+                                                            "state",
+                                                            Context.MAKE_PATH,
+                                                            this.integerEqualEvaluator ) );
+
+        rule.addPattern( contextPattern );
+
+        // ---------------
+        // Seating( seatingId:id, seatingPid:pid, pathDone == false )
+        // ---------------
+        final Pattern seatingPattern = new Pattern( 1,
+                                                    this.seatingType );
+
+        setFieldDeclaration( seatingPattern,
+                             "id",
+                             "seatingId" );
+
+        setFieldDeclaration( seatingPattern,
+                             "pid",
+                             "seatingPid" );
+
+        seatingPattern.addConstraint( getLiteralConstraint( seatingPattern,
+                                                            "pathDone",
+                                                            false,
+                                                            this.booleanEqualEvaluator ) );
+
+        rule.addPattern( seatingPattern );
+
+        final Declaration seatingIdDeclaration = rule.getDeclaration( "seatingId" );
+        final Declaration seatingPidDeclaration = rule.getDeclaration( "seatingPid" );
+
+        // -----------
+        // Path( id == seatingPid, pathGuestName:guestName, pathSeat:seat )
+        // -----------
+        final Pattern pathPattern = new Pattern( 2,
+                                                 this.pathType );
+
+        pathPattern.addConstraint( getBoundVariableConstraint( pathPattern,
+                                                               "id",
+                                                               seatingPidDeclaration,
+                                                               this.integerEqualEvaluator ) );
+
+        setFieldDeclaration( pathPattern,
+                             "guestName",
+                             "pathGuestName" );
+
+        setFieldDeclaration( pathPattern,
+                             "seat",
+                             "pathSeat" );
+
+        rule.addPattern( pathPattern );
+
+        final Declaration pathGuestNameDeclaration = rule.getDeclaration( "pathGuestName" );
+        final Declaration pathSeatDeclaration = rule.getDeclaration( "pathSeat" );
+        // -------------
+        // (not Path( id == seatingId, guestName == pathGuestName )
+        // -------------
+        final Pattern notPathPattern = new Pattern( 3,
+                                                    this.pathType );
+
+        notPathPattern.addConstraint( getBoundVariableConstraint( notPathPattern,
+                                                                  "id",
+                                                                  seatingIdDeclaration,
+                                                                  this.integerEqualEvaluator ) );
+        notPathPattern.addConstraint( getBoundVariableConstraint( notPathPattern,
+                                                                  "guestName",
+                                                                  pathGuestNameDeclaration,
+                                                                  this.objectEqualEvaluator ) );
+
+        final GroupElement not = GroupElementFactory.newNotInstance();
+
+        not.addChild( notPathPattern );
+
+        rule.addPattern( not );
+
+        // ------------
+        // drools.assert( new Path( id, pathName, pathSeat ) );
+        // ------------
+        final Consequence consequence = new Consequence() {
+
+            public void evaluate(KnowledgeHelper drools,
+                                 WorkingMemory workingMemory) throws ConsequenceException {
+                try {
+                    Rule rule = drools.getRule();
+                    Tuple tuple = drools.getTuple();
+
+                    int id = seatingIdDeclaration.getExtractor().getIntValue( (InternalWorkingMemory) workingMemory,
+                                                                              tuple.get( seatingIdDeclaration ).getObject() );
+                    int seat = pathSeatDeclaration.getExtractor().getIntValue( (InternalWorkingMemory) workingMemory,
+                                                                               tuple.get( pathSeatDeclaration ).getObject() );
+                    String guestName = (String) drools.get( pathGuestNameDeclaration );
+
+                    Path path = new Path( id,
+                                          seat,
+                                          guestName );
+
+                    drools.insert( path );
+
+                    //System.err.println( "make path : " + path );
+                } catch ( Exception e ) {
+                    e.printStackTrace();
+                    throw new ConsequenceException( e );
+                }
+            }
+
+        };
+
+        rule.setConsequence( consequence );
+
+        return rule;
+    }
+
+    /**
+     * 
+     * <pre>
+     * rule pathDone() { 
+     *     Context context; Seating seating; 
+     *     when { 
+     *         context : Context( state == Context.MAKE_PATH ) 
+     *         seating : Seating( pathDone == false ) 
+     *     } then { 
+     *         seating.setPathDone( true ); 
+     *         context.setName( Context.CHECK_DONE ); 
+     *     } 
+     * }
+     * </pre>
+     * 
+     * @return
+     * @throws IntrospectionException
+     * @throws InvalidRuleException
+     */
+    private Rule getPathDone() throws IntrospectionException,
+                              InvalidRuleException {
+        final Rule rule = new Rule( "pathDone" );
+
+        // -----------
+        // context : Context( state == Context.MAKE_PATH )
+        // -----------
+        final Pattern contextPattern = new Pattern( 0,
+                                                    this.contextType,
+                                                    "context" );
+
+        contextPattern.addConstraint( getLiteralConstraint( contextPattern,
+                                                            "state",
+                                                            Context.MAKE_PATH,
+                                                            this.integerEqualEvaluator ) );
+
+        rule.addPattern( contextPattern );
+        final Declaration contextDeclaration = rule.getDeclaration( "context" );
+
+        // ---------------
+        // seating : Seating( pathDone == false )
+        // ---------------
+        final Pattern seatingPattern = new Pattern( 1,
+                                                    this.seatingType,
+                                                    "seating" );
+
+        seatingPattern.addConstraint( getLiteralConstraint( seatingPattern,
+                                                            "pathDone",
+                                                            false,
+                                                            this.booleanEqualEvaluator ) );
+
+        rule.addPattern( seatingPattern );
+
+        final Declaration seatingDeclaration = rule.getDeclaration( "seating" );
+
+        // ------------
+        // context.setName( Context.CHECK_DONE );
+        // seating.setPathDone( true );
+        // ------------
+        final Consequence consequence = new Consequence() {
+
+            public void evaluate(KnowledgeHelper drools,
+                                 WorkingMemory workingMemory) throws ConsequenceException {
+                try {
+                    Rule rule = drools.getRule();
+                    Tuple tuple = drools.getTuple();
+
+                    Context context = (Context) drools.get( contextDeclaration );
+                    Seating seating = (Seating) drools.get( seatingDeclaration );
+
+                    drools.modifyRetract( seating );
+                    seating.setPathDone( true );
+
+                    //                    if ( seating.getId() == 6 ) {
+                    //                        System.err.println( "pause" );
+                    //                    }
+                    drools.modifyInsert( seating );
+
+                    context.setState( Context.CHECK_DONE );
+                    drools.update( tuple.get( contextDeclaration ),
+                                   context );
+                    //System.err.println( "path done" + seating );
+                } catch ( Exception e ) {
+                    e.printStackTrace();
+                    throw new ConsequenceException( e );
+                }
+            }
+
+        };
+
+        rule.setConsequence( consequence );
+
+        return rule;
+    }
+
+    /**
+     * <pre>
+     * rule areWeDone() { 
+     *     Context context; LastSeat lastSear; 
+     *     when { 
+     *         context : Context( state == Context.CHECK_DONE ) 
+     *         LastSeat( lastSeat: seat )
+     *         Seating( rightSeat == lastSeat ) 
+     *     } then { 
+     *         context.setState(Context.PRINT_RESULTS ); 
+     *     } 
+     * }
+     * </pre>
+     * 
+     * @return
+     * @throws IntrospectionException
+     * @throws InvalidRuleException
+     */
+    private Rule getAreWeDone() throws IntrospectionException,
+                               InvalidRuleException {
+        final Rule rule = new Rule( "areWeDone" );
+
+        // -----------
+        // context : Context( state == Context.CHECK_DONE )
+        // -----------
+        final Pattern contextPattern = new Pattern( 0,
+                                                    this.contextType,
+                                                    "context" );
+
+        contextPattern.addConstraint( getLiteralConstraint( contextPattern,
+                                                            "state",
+                                                            Context.CHECK_DONE,
+                                                            this.integerEqualEvaluator ) );
+
+        rule.addPattern( contextPattern );
+        final Declaration contextDeclaration = rule.getDeclaration( "context" );
+
+        // ---------------
+        // LastSeat( lastSeat: seat )
+        // ---------------
+        final Pattern lastSeatPattern = new Pattern( 1,
+                                                     this.lastSeatType );
+
+        setFieldDeclaration( lastSeatPattern,
+                             "seat",
+                             "lastSeat" );
+
+        rule.addPattern( lastSeatPattern );
+        final Declaration lastSeatDeclaration = rule.getDeclaration( "lastSeat" );
+        // -------------
+        // Seating( rightSeat == lastSeat )
+        // -------------
+        final Pattern seatingPattern = new Pattern( 2,
+                                                    this.seatingType,
+                                                    null );
+
+        seatingPattern.addConstraint( getBoundVariableConstraint( seatingPattern,
+                                                                  "rightSeat",
+                                                                  lastSeatDeclaration,
+                                                                  this.integerEqualEvaluator ) );
+
+        rule.addPattern( seatingPattern );
+
+        // ------------
+        // context.setName( Context.PRINT_RESULTS );
+        // ------------
+        final Consequence consequence = new Consequence() {
+
+            public void evaluate(KnowledgeHelper drools,
+                                 WorkingMemory workingMemory) throws ConsequenceException {
+                try {
+                    Rule rule = drools.getRule();
+                    Tuple tuple = drools.getTuple();
+
+                    Context context = (Context) drools.get( contextDeclaration );
+                    context.setState( Context.PRINT_RESULTS );
+
+                    drools.update( tuple.get( contextDeclaration ),
+                                   context );
+
+                    System.err.println( "We Are Done!!!" );
+                } catch ( Exception e ) {
+                    throw new ConsequenceException( e );
+                }
+            }
+
+        };
+
+        rule.setConsequence( consequence );
+
+        return rule;
+    }
+
+    /**
+     * <pre>
+     * rule continue() { 
+     *     Context context; 
+     *     when { 
+     *         context : Context( state == Context.CHECK_DONE ) 
+     *     } then { 
+     *         context.setState( Context.ASSIGN_SEATS ); 
+     *     } 
+     * }
+     * </pre>
+     * @return
+     * @throws IntrospectionException
+     * @throws InvalidRuleException
+     */
+    private Rule getContinueProcessing() throws IntrospectionException,
+                                        InvalidRuleException {
+        final Rule rule = new Rule( "continueProcessng" );
+
+        // -----------
+        // context : Context( state == Context.CHECK_DONE )
+        // -----------
+        final Pattern contextPattern = new Pattern( 0,
+                                                    this.contextType,
+                                                    "context" );
+
+        contextPattern.addConstraint( getLiteralConstraint( contextPattern,
+                                                            "state",
+                                                            Context.CHECK_DONE,
+                                                            this.integerEqualEvaluator ) );
+
+        rule.addPattern( contextPattern );
+        final Declaration contextDeclaration = rule.getDeclaration( "context" );
+
+        // ------------
+        // context.setName( Context.ASSIGN_SEATS );
+        // ------------
+        final Consequence consequence = new Consequence() {
+
+            public void evaluate(KnowledgeHelper drools,
+                                 WorkingMemory workingMemory) throws ConsequenceException {
+                try {
+                    Rule rule = drools.getRule();
+                    Tuple tuple = drools.getTuple();
+
+                    Context context = (Context) drools.get( contextDeclaration );
+                    context.setState( Context.ASSIGN_SEATS );
+
+                    drools.update( tuple.get( contextDeclaration ),
+                                   context );
+
+                    //System.err.println( "continue processing" );
+                } catch ( Exception e ) {
+                    e.printStackTrace();
+                    throw new ConsequenceException( e );
+                }
+            }
+
+        };
+
+        rule.setConsequence( consequence );
+
+        return rule;
+    }
+
+    /**
+     * <pre>
+     * rule all_done() { 
+     *     Context context; 
+     *     when { 
+     *         context : Context( state == Context.PRINT_RESULTS ) 
+     *     } then {
+     *     } 
+     * }
+     * </pre>
+     * 
+     * @return
+     * @throws IntrospectionException
+     * @throws InvalidRuleException
+     */
+    private Rule getAllDone() throws IntrospectionException,
+                             InvalidRuleException {
+        final Rule rule = new Rule( "alldone" );
+
+        // -----------
+        // context : Context( state == Context.PRINT_RESULTS )
+        // -----------
+        final Pattern contextPattern = new Pattern( 0,
+                                                    this.contextType );
+
+        contextPattern.addConstraint( getLiteralConstraint( contextPattern,
+                                                            "state",
+                                                            Context.PRINT_RESULTS,
+                                                            this.integerEqualEvaluator ) );
+
+        rule.addPattern( contextPattern );
+        final Declaration contextDeclaration = rule.getDeclaration( "context" );
+
+        // ------------
+        //     
+        // ------------
+        final Consequence consequence = new Consequence() {
+
+            public void evaluate(KnowledgeHelper drools,
+                                 WorkingMemory workingMemory) throws ConsequenceException {
+                try {
+                    System.err.println( "all done" );
+                } catch ( Exception e ) {
+                    throw new ConsequenceException( e );
+                }
+            }
+
+        };
+
+        rule.setConsequence( consequence );
+
+        return rule;
+    }
+
+    /**
+     * Convert the facts from the <code>InputStream</code> to a list of
+     * objects.
+     */
+    protected List getInputObjects(final InputStream inputStream) throws IOException {
+        final List list = new ArrayList();
+
+        final BufferedReader br = new BufferedReader( new InputStreamReader( inputStream ) );
+
+        String line;
+        while ( (line = br.readLine()) != null ) {
+            if ( line.trim().length() == 0 || line.trim().startsWith( ";" ) ) {
+                continue;
+            }
+            final StringTokenizer st = new StringTokenizer( line,
+                                                            "() " );
+            final String type = st.nextToken();
+
+            if ( "guest".equals( type ) ) {
+                if ( !"name".equals( st.nextToken() ) ) {
+                    throw new IOException( "expected 'name' in: " + line );
+                }
+                final String name = st.nextToken();
+                if ( !"sex".equals( st.nextToken() ) ) {
+                    throw new IOException( "expected 'sex' in: " + line );
+                }
+                final String sex = st.nextToken();
+                if ( !"hobby".equals( st.nextToken() ) ) {
+                    throw new IOException( "expected 'hobby' in: " + line );
+                }
+                final String hobby = st.nextToken();
+
+                final Guest guest = new Guest( name,
+                                               Sex.resolve( sex ),
+                                               Hobby.resolve( hobby ) );
+
+                list.add( guest );
+            }
+
+            if ( "last_seat".equals( type ) ) {
+                if ( !"seat".equals( st.nextToken() ) ) {
+                    throw new IOException( "expected 'seat' in: " + line );
+                }
+                list.add( new LastSeat( Integer.parseInt( st.nextToken() ) ) );
+            }
+
+            if ( "context".equals( type ) ) {
+                if ( !"state".equals( st.nextToken() ) ) {
+                    throw new IOException( "expected 'state' in: " + line );
+                }
+                list.add( new Context( st.nextToken() ) );
+            }
+        }
+        inputStream.close();
+
+        return list;
+    }
+
+    private InputStream generateData() {
+        final String LINE_SEPARATOR = System.getProperty( "line.separator" );
+
+        final StringWriter writer = new StringWriter();
+
+        final int maxMale = this.numGuests / 2;
+        final int maxFemale = this.numGuests / 2;
+
+        int maleCount = 0;
+        int femaleCount = 0;
+
+        // init hobbies
+        final List hobbyList = new ArrayList();
+        for ( int i = 1; i <= this.maxHobbies; i++ ) {
+            hobbyList.add( "h" + i );
+        }
+
+        final Random rnd = new Random();
+        for ( int i = 1; i <= this.numGuests; i++ ) {
+            char sex = rnd.nextBoolean() ? 'm' : 'f';
+            if ( sex == 'm' && maleCount == maxMale ) {
+                sex = 'f';
+            }
+            if ( sex == 'f' && femaleCount == maxFemale ) {
+                sex = 'm';
+            }
+            if ( sex == 'm' ) {
+                maleCount++;
+            }
+            if ( sex == 'f' ) {
+                femaleCount++;
+            }
+
+            final List guestHobbies = new ArrayList( hobbyList );
+
+            final int numHobbies = this.minHobbies + rnd.nextInt( this.maxHobbies - this.minHobbies + 1 );
+            for ( int j = 0; j < numHobbies; j++ ) {
+                final int hobbyIndex = rnd.nextInt( guestHobbies.size() );
+                final String hobby = (String) guestHobbies.get( hobbyIndex );
+                writer.write( "(guest (name n" + i + ") (sex " + sex + ") (hobby " + hobby + "))" + LINE_SEPARATOR );
+                guestHobbies.remove( hobbyIndex );
+            }
+        }
+        writer.write( "(last_seat (seat " + this.numSeats + "))" + LINE_SEPARATOR );
+
+        writer.write( LINE_SEPARATOR );
+        writer.write( "(context (state start))" + LINE_SEPARATOR );
+
+        return new ByteArrayInputStream( writer.getBuffer().toString().getBytes() );
+    }
+
+    public static int getIndex(final Class clazz,
+                               final String name) throws IntrospectionException {
+        final PropertyDescriptor[] descriptors = Introspector.getBeanInfo( clazz ).getPropertyDescriptors();
+        for ( int i = 0; i < descriptors.length; i++ ) {
+            if ( descriptors[i].getName().equals( name ) ) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    private AlphaNodeFieldConstraint getLiteralConstraint(final Pattern pattern,
+                                                          final String fieldName,
+                                                          final int fieldValue,
+                                                          final Evaluator evaluator) throws IntrospectionException {
+        final Class clazz = ((ClassObjectType) pattern.getObjectType()).getClassType();
+
+        final FieldExtractor extractor = ClassFieldExtractorCache.getInstance().getExtractor( clazz,
+                                                                                              fieldName,
+                                                                                              getClass().getClassLoader() );
+
+        final FieldValue field = new LongFieldImpl( fieldValue );
+
+        return new LiteralConstraint( extractor,
+                                      evaluator,
+                                      field );
+    }
+
+    private AlphaNodeFieldConstraint getLiteralConstraint(final Pattern pattern,
+                                                          final String fieldName,
+                                                          final boolean fieldValue,
+                                                          final Evaluator evaluator) throws IntrospectionException {
+        final Class clazz = ((ClassObjectType) pattern.getObjectType()).getClassType();
+
+        final FieldExtractor extractor = ClassFieldExtractorCache.getInstance().getExtractor( clazz,
+                                                                                              fieldName,
+                                                                                              getClass().getClassLoader() );
+
+        final FieldValue field = new BooleanFieldImpl( fieldValue );
+
+        return new LiteralConstraint( extractor,
+                                      evaluator,
+                                      field );
+    }
+
+    private void setFieldDeclaration(final Pattern pattern,
+                                     final String fieldName,
+                                     final String identifier) throws IntrospectionException {
+        final Class clazz = ((ClassObjectType) pattern.getObjectType()).getClassType();
+
+        final FieldExtractor extractor = ClassFieldExtractorCache.getInstance().getExtractor( clazz,
+                                                                                              fieldName,
+                                                                                              getClass().getClassLoader() );
+
+        pattern.addDeclaration( identifier,
+                                extractor );
+    }
+
+    private BetaNodeFieldConstraint getBoundVariableConstraint(final Pattern pattern,
+                                                               final String fieldName,
+                                                               final Declaration declaration,
+                                                               final Evaluator evaluator) throws IntrospectionException {
+        final Class clazz = ((ClassObjectType) pattern.getObjectType()).getClassType();
+
+        final FieldExtractor extractor = ClassFieldExtractorCache.getInstance().getExtractor( clazz,
+                                                                                              fieldName,
+                                                                                              getClass().getClassLoader() );
+
+        return new VariableConstraint( extractor,
+                                       declaration,
+                                       evaluator );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Chosen.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Chosen.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Chosen.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.drools.examples.manners;
+
+import java.io.Serializable;
+
+public class Chosen
+    implements
+    Serializable {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    private int               id;
+
+    private String            guestName;
+
+    private Hobby             hobby;
+
+    public Chosen() {
+
+    }
+
+    public Chosen(final int id,
+                  final String guestName,
+                  final Hobby hobby) {
+        this.id = id;
+        this.guestName = guestName;
+        this.hobby = hobby;
+    }
+
+    public int getId() {
+        return this.id;
+    }
+
+    public String getGuestName() {
+        return this.guestName;
+    }
+
+    public Hobby getHobby() {
+        return this.hobby;
+    }
+
+    public String toString() {
+        return "{Chosen id=" + this.id + ", name=" + this.guestName + ", hobbies=" + this.hobby + "}";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Context.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Context.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Context.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.drools.examples.manners;
+
+import java.io.Serializable;
+
+public class Context
+    implements
+    Serializable {
+
+    /**
+     * 
+     */
+    private static final long    serialVersionUID = 400L;
+    public static final int      START_UP         = 0;
+    public static final int      ASSIGN_SEATS     = 1;
+    public static final int      MAKE_PATH        = 2;
+    public static final int      CHECK_DONE       = 3;
+    public static final int      PRINT_RESULTS    = 4;
+
+    public static final String[] stateStrings     = {"START_UP", "ASSIGN_SEATS", "MAKE_PATH", "CHECK_DONE", "PRINT_RESULTS"};
+
+    private int                  state;
+
+    public Context() {
+    }
+
+    public Context(final String state) {
+        if ( "start".equals( state ) ) {
+            this.state = Context.START_UP;
+        } else {
+            throw new RuntimeException( "Context '" + state + "' does not exist for Context Enum" );
+        }
+    }
+
+    public Context(final int state) {
+        this.state = state;
+    }
+
+    public void setState(final int state) {
+        this.state = state;
+    }
+
+    public boolean isState(final int state) {
+        return this.state == state;
+    }
+
+    public int getState() {
+        return this.state;
+    }
+
+    public String getStringValue() {
+        return Context.stateStrings[this.state];
+    }
+
+    public String toString() {
+        return "[Context state=" + getStringValue() + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Count.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Count.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Count.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.drools.examples.manners;
+
+public class Count {
+    private int value;
+
+    public Count() {
+    }
+
+    public Count(final int value) {
+        super();
+        this.value = value;
+    }
+
+    public int getValue() {
+        return this.value;
+    }
+
+    public void setValue(final int value) {
+        this.value = value;
+    }
+
+    public String toString() {
+        return "[Count value=" + this.value + "]";
+    }
+
+    public boolean equals(final Object object) {
+        if ( object == this ) {
+            return true;
+        }
+
+        if ( (object == null) || !(object instanceof Count) ) {
+            return false;
+        }
+
+        return this.value == ((Count) object).value;
+    }
+
+    public int hashCode() {
+        return this.value;
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Guest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Guest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Guest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.drools.examples.manners;
+
+import java.io.Serializable;
+
+public class Guest
+    implements
+    Serializable {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    private String            name;
+
+    private Sex               sex;
+
+    private Hobby             hobby;
+
+    public Guest() {
+    }
+
+    public Guest(final String name,
+                 final Sex sex,
+                 final Hobby hobby) {
+        this.name = name;
+        this.sex = sex;
+        this.hobby = hobby;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public Hobby getHobby() {
+        return this.hobby;
+    }
+
+    public Sex getSex() {
+        return this.sex;
+    }
+
+    public String toString() {
+        return "[Guest name=" + this.name + ", sex=" + this.sex + ", hobbies=" + this.hobby + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Hobby.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Hobby.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Hobby.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.drools.examples.manners;
+
+public class Hobby {
+    public static final String   stringH1     = "h1";
+    public static final String   stringH2     = "h2";
+    public static final String   stringH3     = "h3";
+    public static final String   stringH4     = "h4";
+    public static final String   stringH5     = "h5";
+
+    public static final String[] hobbyStrings = new String[]{Hobby.stringH1, Hobby.stringH2, Hobby.stringH3, Hobby.stringH4, Hobby.stringH5};
+
+    public static final Hobby    H1           = new Hobby( 1 );
+    public static final Hobby    H2           = new Hobby( 2 );
+    public static final Hobby    H3           = new Hobby( 3 );
+    public static final Hobby    H4           = new Hobby( 4 );
+    public static final Hobby    H5           = new Hobby( 5 );
+
+    private String               hobbyStr;
+    private int                  hobbyIndex;
+
+    public Hobby() {
+    }
+
+    private Hobby(final int hobby) {
+        this.hobbyIndex = hobby - 1;
+        this.hobbyStr = Hobby.hobbyStrings[this.hobbyIndex];
+    }
+
+    public String getHobby() {
+        return this.hobbyStr;
+    }
+
+    public final static Hobby resolve(final String hobby) {
+        if ( Hobby.stringH1.equals( hobby ) ) {
+            return Hobby.H1;
+        } else if ( Hobby.stringH2.equals( hobby ) ) {
+            return Hobby.H2;
+        } else if ( Hobby.stringH3.equals( hobby ) ) {
+            return Hobby.H3;
+        } else if ( Hobby.stringH4.equals( hobby ) ) {
+            return Hobby.H4;
+        } else if ( Hobby.stringH5.equals( hobby ) ) {
+            return Hobby.H5;
+        } else {
+            throw new RuntimeException( "Hobby '" + hobby + "' does not exist for Hobby Enum" );
+        }
+    }
+
+    public String toString() {
+        return getHobby();
+    }
+
+    public boolean equals(final Object object) {
+        return (this == object);
+    }
+
+    public int hashCode() {
+        return this.hobbyIndex;
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/LastSeat.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/LastSeat.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/LastSeat.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.drools.examples.manners;
+
+import java.io.Serializable;
+
+public class LastSeat
+    implements
+    Serializable {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+    private int               seat;
+
+    public LastSeat() {
+    }
+
+    public LastSeat(final int seat) {
+        this.seat = seat;
+    }
+
+    public int getSeat() {
+        return this.seat;
+    }
+
+    public String toString() {
+        return "[LastSeat seat=" + this.seat + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Path.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Path.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Path.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.drools.examples.manners;
+
+public class Path {
+    private int    id;
+    private String guestName;
+    private int    seat;
+
+    public Path() {
+    }
+
+    public Path(final int id,
+                final int seat,
+                final String guestName) {
+        this.id = id;
+        this.seat = seat;
+        this.guestName = guestName;
+    }
+
+    public int getSeat() {
+        return this.seat;
+    }
+
+    public String getGuestName() {
+        return this.guestName;
+    }
+
+    public int getId() {
+        return this.id;
+    }
+
+    public String toString() {
+        return "[Path id=" + this.id + ", seat=" + this.seat + ", guest=" + this.guestName + "]";
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/ReteooMannersTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/ReteooMannersTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/ReteooMannersTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,101 @@
+package org.drools.examples.manners;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.InputStream;
+import java.util.Iterator;
+import java.util.List;
+
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.event.AfterActivationFiredEvent;
+import org.drools.event.DefaultAgendaEventListener;
+
+public class ReteooMannersTest extends BaseMannersTest {
+
+    public void testManners() throws Exception {
+
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.RETEOO );
+        ruleBase.addPackage( this.pkg );
+        final WorkingMemory workingMemory = ruleBase.newStatefulSession();
+
+        final DefaultAgendaEventListener listener = new DefaultAgendaEventListener() {
+            private int counter = 0;
+
+            //           public void activationCreated(ActivationCreatedEvent event) {
+            //                super.activationCreated( event );
+            //                System.out.println( event );
+            //            }
+            //           
+            //           public void activationCancelled(ActivationCancelledEvent event) {
+            //               super.activationCancelled( event );
+            //               System.out.println( event );
+            //           }
+            //           
+            //           public void beforeActivationFired(BeforeActivationFiredEvent event) {
+            //               super.beforeActivationFired( event );
+            //               System.out.println( event );
+            //           }           
+
+            public void afterActivationFired(AfterActivationFiredEvent event) {
+                this.counter++;
+                //super.afterActivationFired( event );
+                //System.out.println( event );
+            }
+
+            public String toString() {
+                return "fired :  " + this.counter;
+            }
+
+        };
+
+        //workingMemory.addEventListener(listener );
+        final InputStream is = getClass().getResourceAsStream( "/manners32.dat" );
+        final List list = getInputObjects( is );
+        for ( final Iterator it = list.iterator(); it.hasNext(); ) {
+            final Object object = it.next();
+            workingMemory.insert( object );
+        }
+
+        workingMemory.insert( new Count( 1 ) );
+
+        final long start = System.currentTimeMillis();
+        workingMemory.fireAllRules();
+        System.err.println( System.currentTimeMillis() - start );
+
+        //System.out.println( listener );
+
+        //        while  (1==1){
+        //            Thread.yield();
+        //            Thread.sleep( 2000 );
+        //        }           
+
+        //        final MemoryVisitor visitor = new MemoryVisitor( (InternalWorkingMemory) workingMemory );
+        //        visitor.visit( ruleBase );
+
+        //        final ReteooJungViewer viewer = new ReteooJungViewer(ruleBase); 
+        //        
+        //        javax.swing.SwingUtilities.invokeLater(new Runnable() { 
+        //        		public void run() {
+        //        			viewer.showGUI();
+        //        		}
+        //        });
+        //        
+        //        Thread.sleep( 10000 );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Seating.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Seating.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Seating.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.drools.examples.manners;
+
+import java.io.Serializable;
+
+public class Seating
+    implements
+    Serializable {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    private int               id, pid;
+
+    private int               leftSeat, rightSeat;
+
+    private String            leftGuestName, rightGuestName;
+
+    private boolean           pathDone;
+
+    public Seating() {
+    }
+
+    public Seating(final int id,
+                   final int pid,
+                   final boolean pathDone,
+                   final int leftSeat,
+                   final String leftGuestName,
+                   final int rightSeat,
+                   final String rightGuestName) {
+        super();
+        this.id = id;
+        this.pid = pid;
+        this.pathDone = pathDone;
+        this.leftSeat = leftSeat;
+        this.leftGuestName = leftGuestName;
+        this.rightSeat = rightSeat;
+        this.rightGuestName = rightGuestName;
+    }
+
+    public boolean isPathDone() {
+        return this.pathDone;
+    }
+
+    public void setPathDone(final boolean pathDone) {
+        this.pathDone = pathDone;
+    }
+
+    public int getId() {
+        return this.id;
+    }
+
+    public String getLeftGuestName() {
+        return this.leftGuestName;
+    }
+
+    public int getLeftSeat() {
+        return this.leftSeat;
+    }
+
+    public int getPid() {
+        return this.pid;
+    }
+
+    public String getRightGuestName() {
+        return this.rightGuestName;
+    }
+
+    public int getRightSeat() {
+        return this.rightSeat;
+    }
+
+    public String toString() {
+        return "[Seating id=" + this.id + " , pid=" + this.pid + " , pathDone=" + this.pathDone + " , leftSeat=" + this.leftSeat + ", leftGuestName=" + this.leftGuestName + ", rightSeat=" + this.rightSeat + ", rightGuestName=" + this.rightGuestName
+               + "]";
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Sex.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Sex.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/examples/manners/Sex.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.drools.examples.manners;
+
+public class Sex {
+    public static final Sex      M       = new Sex( 0 );
+    public static final Sex      F       = new Sex( 1 );
+
+    public static final String   stringM = "m";
+    public static final String   stringF = "f";
+    public static final String[] sexList = new String[]{Sex.stringM, Sex.stringF};
+
+    private int                  sex;
+
+    public Sex() {
+    }
+
+    private Sex(final int sex) {
+        this.sex = sex;
+    }
+
+    public String getSex() {
+        return Sex.sexList[this.sex];
+    }
+
+    public final static Sex resolve(final String sex) {
+        if ( Sex.stringM.equals( sex ) ) {
+            return Sex.M;
+        } else if ( Sex.stringF.equals( sex ) ) {
+            return Sex.F;
+        } else {
+            throw new RuntimeException( "Sex '" + sex + "' does not exist for Sex Enum" );
+        }
+    }
+
+    public String toString() {
+        return getSex();
+    }
+
+    public boolean equals(final Object object) {
+        return this == object;
+    }
+
+    public int hashCode() {
+        return this.sex;
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/facttemplates/FactTemplateFieldExtractorTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/facttemplates/FactTemplateFieldExtractorTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/facttemplates/FactTemplateFieldExtractorTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,105 @@
+package org.drools.facttemplates;
+
+import junit.framework.TestCase;
+
+import org.drools.rule.Pattern;
+import org.drools.rule.Declaration;
+import org.drools.rule.Package;
+import org.drools.spi.Extractor;
+
+public class FactTemplateFieldExtractorTest extends TestCase {
+    public void testExtractor() {
+        final Package pkg = new Package( "org.store" );
+
+        final FieldTemplate cheeseName = new FieldTemplateImpl( "name",
+                                                                0,
+                                                                String.class );
+        final FieldTemplate cheesePrice = new FieldTemplateImpl( "price",
+                                                                 1,
+                                                                 Integer.class );
+        final FieldTemplate[] fields = new FieldTemplate[]{cheeseName, cheesePrice};
+        final FactTemplate cheese = new FactTemplateImpl( pkg,
+                                                          "Cheese",
+                                                          fields );
+
+        final Extractor extractName = new FactTemplateFieldExtractor( cheese,
+                                                                      0 );
+        final Extractor extractPrice = new FactTemplateFieldExtractor( cheese,
+                                                                       1 );
+
+        final Fact stilton = cheese.createFact( 10 );
+        stilton.setFieldValue( "name",
+                               "stilton" );
+        stilton.setFieldValue( "price",
+                               new Integer( 200 ) );
+
+        assertEquals( "stilton",
+                      extractName.getValue( null, stilton ) );
+
+        assertEquals( new Integer( 200 ),
+                      extractPrice.getValue( null, stilton ) );
+
+        assertFalse( extractName.isNullValue( null, stilton ) );
+        
+        stilton.setFieldValue( "name",
+                               null );
+        
+        assertTrue( extractName.isNullValue( null, stilton ) );
+        assertFalse( extractPrice.isNullValue( null, stilton ) );
+        
+        final Fact brie = cheese.createFact( 12 );
+        brie.setFieldValue( "name",
+                            "brie" );
+        brie.setFieldValue( "price",
+                            new Integer( 55 ) );
+
+        assertEquals( "brie",
+                      extractName.getValue( null, brie ) );
+
+        assertEquals( new Integer( 55 ),
+                      extractPrice.getValue( null, brie ) );
+        
+        assertFalse( extractName.isNullValue( null, brie ) );
+        
+        brie.setFieldValue( "name",
+                            null );
+        
+        assertTrue( extractName.isNullValue( null, brie ) );
+        assertFalse( extractPrice.isNullValue( null, stilton ) );
+    }
+
+    public void testDeclaration() {
+        final Package pkg = new Package( "org.store" );
+
+        final FieldTemplate cheeseName = new FieldTemplateImpl( "name",
+                                                                0,
+                                                                String.class );
+        final FieldTemplate cheesePrice = new FieldTemplateImpl( "price",
+                                                                 1,
+                                                                 Integer.class );
+        final FieldTemplate[] fields = new FieldTemplate[]{cheeseName, cheesePrice};
+        final FactTemplate cheese = new FactTemplateImpl( pkg,
+                                                          "Cheese",
+                                                          fields );
+
+        final Extractor extractName = new FactTemplateFieldExtractor( cheese,
+                                                                      0 );
+
+        final Pattern pattern = new Pattern( 0,
+                                          new FactTemplateObjectType( cheese ) );
+
+        final Declaration declaration = new Declaration( "typeOfCheese",
+                                                         extractName,
+                                                         pattern );
+
+        final Fact brie = cheese.createFact( 12 );
+        brie.setFieldValue( "name",
+                            "brie" );
+        brie.setFieldValue( "price",
+                            new Integer( 55 ) );
+
+        // Check we can extract Declarations correctly 
+        assertEquals( "brie",
+                      declaration.getValue( null, brie ) );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/facttemplates/FactTemplateTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/facttemplates/FactTemplateTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/facttemplates/FactTemplateTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,141 @@
+package org.drools.facttemplates;
+
+import junit.framework.TestCase;
+
+import org.drools.rule.Package;
+
+public class FactTemplateTest extends TestCase {
+    public void testFieldsAndGetters() {
+        final Package pkg = new Package( "org.store" );
+        final FieldTemplate cheeseName = new FieldTemplateImpl( "name",
+                                                                0,
+                                                                String.class );
+        final FieldTemplate cheesePrice = new FieldTemplateImpl( "price",
+                                                                 1,
+                                                                 Integer.class );
+        final FieldTemplate[] fields = new FieldTemplate[]{cheeseName, cheesePrice};
+        final FactTemplate cheese = new FactTemplateImpl( pkg,
+                                                          "Cheese",
+                                                          fields );
+
+        assertEquals( "org.store",
+                      cheese.getPackage().getName() );
+        assertEquals( "Cheese",
+                      cheese.getName() );
+
+        assertEquals( 2,
+                      cheese.getNumberOfFields() );
+
+        assertSame( fields,
+                    cheese.getAllFieldTemplates() );
+
+        assertSame( cheeseName,
+                    cheese.getFieldTemplate( 0 ) );
+        assertSame( cheesePrice,
+                    cheese.getFieldTemplate( 1 ) );
+
+        assertSame( cheeseName,
+                    cheese.getFieldTemplate( "name" ) );
+        assertSame( cheesePrice,
+                    cheese.getFieldTemplate( "price" ) );
+
+        assertEquals( 0,
+                      cheese.getFieldTemplateIndex( "name" ) );
+        assertEquals( 1,
+                      cheese.getFieldTemplateIndex( "price" ) );
+    }
+
+    public void testEqualsAndHashCode() {
+        final Package pkg = new Package( "org.store" );
+
+        // Create cheese1 with name and price fields
+        final FieldTemplate cheeseName = new FieldTemplateImpl( "name",
+                                                                0,
+                                                                String.class );
+        final FieldTemplate cheesePrice = new FieldTemplateImpl( "price",
+                                                                 1,
+                                                                 Integer.class );
+        final FieldTemplate[] fields1 = new FieldTemplate[]{cheeseName, cheesePrice};
+        final FactTemplate cheese1 = new FactTemplateImpl( pkg,
+                                                           "Cheese",
+                                                           fields1 );
+
+        // Create cheese2 with type and price fields
+        final FieldTemplate cheeseType = new FieldTemplateImpl( "type",
+                                                                0,
+                                                                String.class );
+        final FieldTemplate[] fields2 = new FieldTemplate[]{cheeseType, cheesePrice};
+        final FactTemplate cheese2 = new FactTemplateImpl( pkg,
+                                                           "Cheese",
+                                                           fields2 );
+
+        assertNotSame( cheese1,
+                       cheese2 );
+
+        assertFalse( cheese1.equals( cheese2 ) );
+
+        assertFalse( cheese1.hashCode() == cheese2.hashCode() );
+
+        // create cheese3 with name and price fields, using new instances
+        final FieldTemplate cheeseName2 = new FieldTemplateImpl( "name",
+                                                                 0,
+                                                                 String.class );
+        final FieldTemplate cheesePrice2 = new FieldTemplateImpl( "price",
+                                                                  1,
+                                                                  Integer.class );
+        final FieldTemplate[] fields3 = new FieldTemplate[]{cheeseName2, cheesePrice2};
+        final FactTemplate cheese3 = new FactTemplateImpl( pkg,
+                                                           "Cheese",
+                                                           fields3 );
+
+        assertNotSame( cheese1,
+                       cheese3 );
+        assertNotSame( cheese1.getAllFieldTemplates(),
+                       cheese3.getAllFieldTemplates() );
+        assertEquals( cheese1,
+                      cheese3 );
+        assertEquals( cheese1.hashCode(),
+                      cheese3.hashCode() );
+    }
+
+    public void testFacts() {
+        final Package pkg = new Package( "org.store" );
+        final FieldTemplate cheeseName = new FieldTemplateImpl( "name",
+                                                                0,
+                                                                String.class );
+        final FieldTemplate cheesePrice = new FieldTemplateImpl( "price",
+                                                                 1,
+                                                                 Integer.class );
+        final FieldTemplate[] fields1 = new FieldTemplate[]{cheeseName, cheesePrice};
+        final FactTemplate cheese1 = new FactTemplateImpl( pkg,
+                                                           "Cheese",
+                                                           fields1 );
+
+        final Fact stilton1 = cheese1.createFact( 10 );
+        stilton1.setFieldValue( "name",
+                                "stilton" );
+        stilton1.setFieldValue( "price",
+                                new Integer( 200 ) );
+
+        final Fact stilton2 = cheese1.createFact( 11 );
+        stilton2.setFieldValue( 0,
+                                "stilton" );
+        stilton2.setFieldValue( 1,
+                                new Integer( 200 ) );
+
+        assertEquals( stilton1,
+                      stilton2 );
+        assertEquals( stilton1.hashCode(),
+                      stilton2.hashCode() );
+
+        final Fact brie = cheese1.createFact( 12 );
+        brie.setFieldValue( "name",
+                            "brie" );
+        brie.setFieldValue( "price",
+                            new Integer( 55 ) );
+
+        assertFalse( stilton1.equals( brie ) );
+        assertFalse( stilton1.hashCode() == brie.hashCode() );
+
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/facttemplates/FieldTemplateTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/facttemplates/FieldTemplateTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/facttemplates/FieldTemplateTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,20 @@
+package org.drools.facttemplates;
+
+import junit.framework.TestCase;
+
+import org.drools.base.ValueType;
+
+public class FieldTemplateTest extends TestCase {
+    public void testFieldTemplate() {
+        final FieldTemplate cheeseName = new FieldTemplateImpl( "name",
+                                                                5,
+                                                                String.class );
+        assertEquals( "name",
+                      cheeseName.getName() );
+        assertEquals( ValueType.STRING_TYPE,
+                      cheeseName.getValueType() );
+        assertEquals( 5,
+                      cheeseName.getIndex() );
+
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/AccumulateNodeTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/AccumulateNodeTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/AccumulateNodeTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,473 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.drools.reteoo;
+
+import junit.framework.Assert;
+
+import org.drools.DroolsTestCase;
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuleBaseFactory;
+import org.drools.base.ClassObjectType;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.EmptyBetaConstraints;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.reteoo.AccumulateNode.AccumulateMemory;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.Accumulate;
+import org.drools.rule.Declaration;
+import org.drools.rule.Pattern;
+import org.drools.rule.Rule;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.MockConstraint;
+import org.drools.spi.ObjectType;
+import org.drools.spi.PropagationContext;
+
+/**
+ * A test case for AccumulateNode
+ * 
+ * @author etirelli
+ */
+public class AccumulateNodeTest extends DroolsTestCase {
+
+    Rule                rule;
+    PropagationContext  context;
+    ReteooWorkingMemory workingMemory;
+    MockObjectSource    objectSource;
+    MockTupleSource     tupleSource;
+    MockTupleSink       sink;
+    BetaNode            node;
+    BetaMemory          memory;
+    MockConstraint      constraint = new MockConstraint();
+    MockAccumulator     accumulator;
+    Accumulate          accumulate;
+
+    /* (non-Javadoc)
+     * @see junit.framework.TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+        super.setUp();
+        this.rule = new Rule( "test-rule" );
+        this.context = new PropagationContextImpl( 0,
+                                                   PropagationContext.ASSERTION,
+                                                   null,
+                                                   null );
+        
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ruleBase.getReteooBuilder().getIdGenerator() );
+        
+        this.workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        this.tupleSource = new MockTupleSource( 4 );
+        this.objectSource = new MockObjectSource( 4 );
+        this.sink = new MockTupleSink();
+
+        this.accumulator = new MockAccumulator();
+
+        final ObjectType srcObjType = new ClassObjectType( String.class );
+        final Pattern sourcePattern = new Pattern( 0,
+                                                srcObjType );
+        this.accumulate = new Accumulate( sourcePattern,
+                                          new Declaration[0],
+                                          new Declaration[0],
+                                          this.accumulator );
+        
+        
+
+        this.node = new AccumulateNode( 15,
+                                        this.tupleSource,
+                                        this.objectSource,
+                                        new AlphaNodeFieldConstraint[0],
+                                        EmptyBetaConstraints.getInstance(),
+                                        EmptyBetaConstraints.getInstance(),
+                                        this.accumulate,
+                                        false,
+                                        buildContext );
+
+        this.node.addTupleSink( this.sink );
+
+        this.memory = ((AccumulateMemory) this.workingMemory.getNodeMemory( this.node )).betaMemory;
+
+        // check memories are empty
+        assertEquals( 0,
+                      this.memory.getTupleMemory().size() );
+        assertEquals( 0,
+                      this.memory.getFactHandleMemory().size() );
+    }
+
+    /* (non-Javadoc)
+     * @see junit.framework.TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * Test method for {@link org.drools.reteoo.AccumulateNode#updateNewNode(InternalWorkingMemory, org.drools.spi.PropagationContext)}.
+     */
+    public void testUpdateSink() {
+        this.node.updateSink( this.sink,
+                              this.context,
+                              this.workingMemory );
+        Assert.assertEquals( "No tuple should be propagated",
+                             0,
+                             this.sink.getAsserted().size() );
+
+        this.node.assertTuple( new ReteTuple( this.workingMemory.getFactHandleFactory().newFactHandle( "cheese", false, null ) ),
+                               this.context,
+                               this.workingMemory );
+        this.node.assertTuple( new ReteTuple( this.workingMemory.getFactHandleFactory().newFactHandle( "other cheese", false, null ) ),
+                               this.context,
+                               this.workingMemory );
+
+        Assert.assertEquals( "Two tuples should have been propagated",
+                             2,
+                             this.sink.getAsserted().size() );
+
+        final MockTupleSink otherSink = new MockTupleSink();
+
+        this.node.addTupleSink( otherSink );
+        this.node.updateSink( otherSink,
+                              this.context,
+                              this.workingMemory );
+
+        Assert.assertEquals( "Two tuples should have been propagated",
+                             2,
+                             otherSink.getAsserted().size() );
+    }
+
+    /**
+     * Test method for {@link org.drools.reteoo.AccumulateNode#assertTuple(org.drools.reteoo.ReteTuple, org.drools.spi.PropagationContext, org.drools.reteoo.ReteooWorkingMemory)}.
+     */
+    public void testAssertTuple() {
+        final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.getFactHandleFactory().newFactHandle( "cheese", false, null );
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        // assert tuple, should add one to left memory
+        this.node.assertTuple( tuple0,
+                               this.context,
+                               this.workingMemory );
+        // check memories 
+        assertEquals( 1,
+                      this.memory.getTupleMemory().size() );
+        assertEquals( 0,
+                      this.memory.getFactHandleMemory().size() );
+        Assert.assertTrue( "An empty matching objects list should be propagated",
+                           this.accumulator.getMatchingObjects().isEmpty() );
+
+        // assert tuple, should add left memory 
+        final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.getFactHandleFactory().newFactHandle( "other cheese", false, null );
+
+        final ReteTuple tuple1 = new ReteTuple( f1 );
+        this.node.assertTuple( tuple1,
+                               this.context,
+                               this.workingMemory );
+        assertEquals( 2,
+                      this.memory.getTupleMemory().size() );
+        Assert.assertTrue( "An empty matching objects list should be propagated",
+                           this.accumulator.getMatchingObjects().isEmpty() );
+
+        final TupleMemory memory = this.memory.getTupleMemory();
+        assertTrue( memory.contains( tuple0 ) );
+        assertTrue( memory.contains( tuple1 ) );
+
+        Assert.assertEquals( "Two tuples should have been propagated",
+                             2,
+                             this.sink.getAsserted().size() );
+    }
+
+    /**
+     * Test method for {@link org.drools.reteoo.AccumulateNode#assertTuple(org.drools.reteoo.ReteTuple, org.drools.spi.PropagationContext, org.drools.reteoo.ReteooWorkingMemory)}.
+     */
+    public void testAssertTupleWithObjects() {
+        final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.getFactHandleFactory().newFactHandle( "cheese", false, null );
+        final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.getFactHandleFactory().newFactHandle( "other cheese", false, null );
+
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        this.node.assertObject( f0,
+                                this.context,
+                                this.workingMemory );
+        this.node.assertObject( f1,
+                                this.context,
+                                this.workingMemory );
+
+        // assert tuple, should add one to left memory
+        this.node.assertTuple( tuple0,
+                               this.context,
+                               this.workingMemory );
+        // check memories 
+        assertEquals( 1,
+                      this.memory.getTupleMemory().size() );
+        assertEquals( 2,
+                      this.memory.getFactHandleMemory().size() );
+        Assert.assertEquals( "Wrong number of elements in matching objects list ",
+                             2,
+                             this.accumulator.getMatchingObjects().size() );
+
+        // assert tuple, should add left memory 
+        final ReteTuple tuple1 = new ReteTuple( f1 );
+        this.node.assertTuple( tuple1,
+                               this.context,
+                               this.workingMemory );
+        assertEquals( 2,
+                      this.memory.getTupleMemory().size() );
+        Assert.assertEquals( "Wrong number of elements in matching objects list ",
+                             2,
+                             this.accumulator.getMatchingObjects().size() );
+
+        final TupleMemory memory = this.memory.getTupleMemory();
+        assertTrue( memory.contains( tuple0 ) );
+        assertTrue( memory.contains( tuple1 ) );
+
+        Assert.assertEquals( "Two tuples should have been propagated",
+                             2,
+                             this.sink.getAsserted().size() );
+    }
+
+    /**
+     * Test method for {@link org.drools.reteoo.AccumulateNode#retractTuple(org.drools.reteoo.ReteTuple, org.drools.spi.PropagationContext, org.drools.reteoo.ReteooWorkingMemory)}.
+     */
+    public void testRetractTuple() {
+        final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.getFactHandleFactory().newFactHandle( "cheese", false, null );
+
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        // assert tuple, should add one to left memory
+        this.node.assertTuple( tuple0,
+                               this.context,
+                               this.workingMemory );
+        // check memories 
+        assertEquals( 1,
+                      this.memory.getTupleMemory().size() );
+        assertEquals( 0,
+                      this.memory.getFactHandleMemory().size() );
+        Assert.assertTrue( "An empty matching objects list should be propagated",
+                           this.accumulator.getMatchingObjects().isEmpty() );
+
+        this.node.retractTuple( tuple0,
+                                this.context,
+                                this.workingMemory );
+        assertEquals( 0,
+                      this.memory.getTupleMemory().size() );
+        assertEquals( 1,
+                      this.sink.getRetracted().size() );
+        assertEquals( 1,
+                      this.sink.getAsserted().size() );
+    }
+
+    /**
+     * Test method for {@link org.drools.reteoo.AccumulateNode#assertObject(InternalFactHandle, org.drools.spi.PropagationContext, InternalWorkingMemory)}.
+     */
+    public void testAssertObject() {
+        final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.getFactHandleFactory().newFactHandle( "cheese", false, null );
+        final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.getFactHandleFactory().newFactHandle( "other cheese", false, null );
+
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        // assert tuple, should add one to left memory
+        this.node.assertTuple( tuple0,
+                               this.context,
+                               this.workingMemory );
+
+        // check memory 
+        assertEquals( 1,
+                      this.memory.getTupleMemory().size() );
+        assertEquals( 1,
+                      this.sink.getAsserted().size() );
+        assertEquals( 0,
+                      this.accumulator.getMatchingObjects().size() );
+
+        this.node.assertObject( f0,
+                                this.context,
+                                this.workingMemory );
+        assertEquals( 1,
+                      this.memory.getFactHandleMemory().size() );
+        assertEquals( 2,
+                      this.sink.getAsserted().size() );
+        assertEquals( 1,
+                      this.accumulator.getMatchingObjects().size() );
+
+        this.node.assertObject( f1,
+                                this.context,
+                                this.workingMemory );
+
+        assertEquals( 2,
+                      this.memory.getFactHandleMemory().size() );
+        assertEquals( 3,
+                      this.sink.getAsserted().size() );
+        assertEquals( 2,
+                      this.accumulator.getMatchingObjects().size() );
+
+    }
+
+    /**
+     * Test method for {@link org.drools.reteoo.AccumulateNode#retractObject(InternalFactHandle, org.drools.spi.PropagationContext, InternalWorkingMemory)}.
+     */
+    public void testRetractObject() {
+        final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.getFactHandleFactory().newFactHandle( "cheese", false, null );
+        final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.getFactHandleFactory().newFactHandle( "other cheese", false, null );
+
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        this.node.assertObject( f0,
+                                this.context,
+                                this.workingMemory );
+        this.node.assertObject( f1,
+                                this.context,
+                                this.workingMemory );
+        assertEquals( 2,
+                      this.memory.getFactHandleMemory().size() );
+
+        // assert tuple, should add one to left memory
+        this.node.assertTuple( tuple0,
+                               this.context,
+                               this.workingMemory );
+
+        // check memory 
+        assertEquals( 1,
+                      this.memory.getTupleMemory().size() );
+        assertEquals( 0,
+                      this.sink.getRetracted().size() );
+        assertEquals( 1,
+                      this.sink.getAsserted().size() );
+        assertEquals( 2,
+                      this.accumulator.getMatchingObjects().size() );
+
+        this.node.retractObject( f1,
+                                 this.context,
+                                 this.workingMemory );
+        assertEquals( 1,
+                      this.memory.getFactHandleMemory().size() );
+        assertEquals( 1,
+                      this.sink.getRetracted().size() );
+        assertEquals( 2,
+                      this.sink.getAsserted().size() );
+        assertEquals( 1,
+                      this.accumulator.getMatchingObjects().size() );
+
+        this.node.retractObject( f0,
+                                 this.context,
+                                 this.workingMemory );
+        assertEquals( 0,
+                      this.memory.getFactHandleMemory().size() );
+        assertEquals( 2,
+                      this.sink.getRetracted().size() );
+        assertEquals( 3,
+                      this.sink.getAsserted().size() );
+        assertEquals( 0,
+                      this.accumulator.getMatchingObjects().size() );
+
+    }
+
+    public void testMemory() {
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ruleBase.getReteooBuilder().getIdGenerator() );
+        
+        this.workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final MockObjectSource objectSource = new MockObjectSource( 1 );
+        final MockTupleSource tupleSource = new MockTupleSource( 1 );
+
+        final AccumulateNode accumulateNode = new AccumulateNode( 2,
+                                                                  tupleSource,
+                                                                  objectSource,
+                                                                  new AlphaNodeFieldConstraint[0],
+                                                                  EmptyBetaConstraints.getInstance(),
+                                                                  EmptyBetaConstraints.getInstance(),
+                                                                  this.accumulate,
+                                                                  false,
+                                                                  buildContext  );
+
+        final BetaMemory memory = ((AccumulateMemory) this.workingMemory.getNodeMemory( accumulateNode )).betaMemory;
+
+        assertNotNull( memory );
+    }
+
+    /**
+     * Test just tuple assertions
+     * 
+     * @throws AssertionException
+     */
+    public void testAssertTupleSequentialMode() throws Exception {
+        RuleBaseConfiguration conf = new RuleBaseConfiguration();
+        conf.setSequential( true );
+
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ruleBase.getReteooBuilder().getIdGenerator() );
+        buildContext.setTupleMemoryEnabled( false );
+        // overide the original node, so we an set the BuildContext
+        this.node = new AccumulateNode( 15,
+                                        this.tupleSource,
+                                        this.objectSource,
+                                        new AlphaNodeFieldConstraint[0],
+                                        EmptyBetaConstraints.getInstance(),
+                                        EmptyBetaConstraints.getInstance(),
+                                        this.accumulate,
+                                        false,
+                                        buildContext );
+
+        this.node.addTupleSink( this.sink );        
+        
+        this.workingMemory = new ReteooWorkingMemory( 1,
+                                                      (ReteooRuleBase) RuleBaseFactory.newRuleBase( conf ) );
+        
+        this.memory = ((AccumulateMemory) this.workingMemory.getNodeMemory( this.node )).betaMemory;
+
+        final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.getFactHandleFactory().newFactHandle( "cheese", false, null );
+        final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.getFactHandleFactory().newFactHandle( "other cheese", false, null );
+
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        this.node.assertObject( f0,
+                                this.context,
+                                this.workingMemory );
+        this.node.assertObject( f1,
+                                this.context,
+                                this.workingMemory );
+
+        // assert tuple, should not add to left memory, since we are in sequential mode
+        this.node.assertTuple( tuple0,
+                               this.context,
+                               this.workingMemory );
+        // check memories 
+        assertNull( this.memory.getTupleMemory() );
+        assertEquals( 2,
+                      this.memory.getFactHandleMemory().size() );
+        Assert.assertEquals( "Wrong number of elements in matching objects list ",
+                             2,
+                             this.accumulator.getMatchingObjects().size() );
+
+        // assert tuple, should not add left memory 
+        final ReteTuple tuple1 = new ReteTuple( f1 );
+        this.node.assertTuple( tuple1,
+                               this.context,
+                               this.workingMemory );
+        assertNull( this.memory.getTupleMemory() );
+        Assert.assertEquals( "Wrong number of elements in matching objects list ",
+                             2,
+                             this.accumulator.getMatchingObjects().size() );
+
+        Assert.assertEquals( "Two tuples should have been propagated",
+                             2,
+                             this.sink.getAsserted().size() );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/AddRemoveTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/AddRemoveTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/AddRemoveTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,52 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.DroolsTestCase;
+import org.drools.RuleBaseFactory;
+import org.drools.base.ClassObjectType;
+import org.drools.reteoo.builder.BuildContext;
+
+public class AddRemoveTest extends DroolsTestCase {
+    public void testAdd() {
+        /*
+         * create a RuleBase with a single ObjectTypeNode we attach a
+         * MockObjectSink so we can detect assertions and retractions
+         */
+        final ReteooRuleBase ruleBase = ( ReteooRuleBase ) RuleBaseFactory.newRuleBase();        
+        BuildContext context = new BuildContext(ruleBase, ruleBase.getReteooBuilder().getIdGenerator() );
+        
+        final EntryPointNode entryPoint = new EntryPointNode( -1,
+                                                              ruleBase.getRete(),
+                                                              context );
+        entryPoint.attach();
+                        
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( 0,
+                                                                  entryPoint,
+                                                                  new ClassObjectType( Object.class ),
+                                                                  context );
+        objectTypeNode.attach();
+
+        final MockObjectSink sink = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink );
+       
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        // objectTypeNode.
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/AgendaTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/AgendaTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/AgendaTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,1669 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.Agenda;
+import org.drools.DroolsTestCase;
+import org.drools.RuleBase;
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.base.SalienceInteger;
+import org.drools.common.ArrayAgendaGroup;
+import org.drools.common.BinaryHeapQueueAgendaGroup;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalAgenda;
+import org.drools.common.InternalAgendaGroup;
+import org.drools.common.InternalRuleBase;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.common.RuleFlowGroupImpl;
+import org.drools.conflict.DepthConflictResolver;
+import org.drools.reteoo.ReteooBuilder.IdGenerator;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.Rule;
+import org.drools.spi.Activation;
+import org.drools.spi.ActivationGroup;
+import org.drools.spi.AgendaFilter;
+import org.drools.spi.AgendaGroup;
+import org.drools.spi.Consequence;
+import org.drools.spi.ConsequenceException;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.RuleFlowGroup;
+
+/**
+ * @author mproctor
+ */
+
+public class AgendaTest extends DroolsTestCase {
+    private InternalRuleBase ruleBase;
+    private BuildContext buildContext;
+    
+    protected void setUp() throws Exception {
+        ruleBase = ( InternalRuleBase ) RuleBaseFactory.newRuleBase();
+        buildContext = new BuildContext( ruleBase, ((ReteooRuleBase)ruleBase).getReteooBuilder().getIdGenerator() );
+    }
+    
+    public void testClearAgenda() {
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final Agenda agenda = workingMemory.getAgenda();
+
+        final Rule rule1 = new Rule( "test-rule1" );
+        final Rule rule2 = new Rule( "test-rule2" );
+
+        final RuleTerminalNode node1 = new RuleTerminalNode( 3,
+                                                             new MockTupleSource( 2 ),
+                                                             rule1,
+                                                             rule1.getLhs(),
+                                                             buildContext );
+        
+        final RuleTerminalNode node2 = new RuleTerminalNode( 5,
+                                                             new MockTupleSource( 4 ),
+                                                             rule2,
+                                                             rule2.getLhs(),
+                                                             buildContext );        
+
+        final ReteTuple tuple = new ReteTuple( new DefaultFactHandle( 1,
+                                                                      "cheese" ) );
+
+        final PropagationContext context1 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule1,
+                                                                        null );
+
+        // Add consequence. Notice here the context here for the add to ageyunda
+        // is itself
+        rule1.setConsequence( new org.drools.spi.Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(final KnowledgeHelper knowledgeHelper,
+                                 final WorkingMemory workingMemory) {
+                // do nothing
+            }
+        } );
+        
+        // Add consequence. Notice here the context here for the add to ageyunda
+        // is itself
+        rule2.setConsequence( new org.drools.spi.Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(final KnowledgeHelper knowledgeHelper,
+                                 final WorkingMemory workingMemory) {
+                // do nothing
+            }
+        } );        
+
+        assertEquals( 0,
+                      agenda.getFocus().size() );
+
+        rule1.setNoLoop( false );
+        rule2.setDuration( 5000 );
+        
+        node1.assertTuple( tuple,
+                           context1,
+                           workingMemory );
+        
+        node2.assertTuple( tuple,
+                           context1,
+                           workingMemory );                
+
+        // make sure we have an activation in the current focus
+        assertEquals( 1,
+                      agenda.getFocus().size() );
+        
+        assertEquals( 1,
+                      agenda.getScheduledActivations().length );
+        
+
+        agenda.clearAgenda();
+
+        assertEquals( 0,
+                      agenda.getFocus().size() );
+        
+        assertEquals( 0,
+                      agenda.getScheduledActivations().length );        
+    }
+
+    public void testFilters() throws Exception {
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+        
+        final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+        final Rule rule = new Rule( "test-rule" );
+        final RuleTerminalNode node = new RuleTerminalNode( 3,
+                                                            new MockTupleSource( 2 ),
+                                                            rule,
+                                                            rule.getLhs(),
+                                                            buildContext );
+
+        final Map results = new HashMap();
+        // add consequence
+        rule.setConsequence( new org.drools.spi.Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(final KnowledgeHelper knowledgeHelper,
+                                 final WorkingMemory workingMemory) {
+                results.put( "fired",
+                             new Boolean( true ) );
+            }
+        } );
+
+        final ReteTuple tuple = new ReteTuple( new DefaultFactHandle( 1,
+                                                                      "cheese" ) );
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       rule,
+                                                                       null );
+
+        // test agenda is empty
+        assertEquals( 0,
+                      agenda.getFocus().size() );
+
+        // True filter, activations should always add
+        final AgendaFilter filterTrue = new AgendaFilter() {
+            public boolean accept(Activation item) {
+                return true;
+            }
+        };
+
+        rule.setNoLoop( false );
+        node.assertTuple( tuple,
+                          context,
+                          workingMemory );
+
+        // check there is an item to fire
+        assertEquals( 1,
+                      agenda.getFocus().size() );
+        agenda.fireNextItem( filterTrue );
+
+        // check focus is empty
+        assertEquals( 0,
+                      agenda.getFocus().size() );
+
+        // make sure it also fired
+        assertEquals( new Boolean( true ),
+                      results.get( "fired" ) );
+
+        // clear the agenda and the result map
+        agenda.clearAgenda();
+        results.clear();
+
+        // False filter, activations should always be denied
+        final AgendaFilter filterFalse = new AgendaFilter() {
+            public boolean accept(Activation item) {
+                return false;
+            }
+        };
+
+        rule.setNoLoop( false );
+        node.assertTuple( tuple,
+                          context,
+                          workingMemory );
+
+        // check we have an item to fire
+        assertEquals( 1,
+                      agenda.getFocus().size() );
+        agenda.fireNextItem( filterFalse );
+
+        // make sure the focus is empty
+        assertEquals( 0,
+                      agenda.getFocus().size() );
+
+        // check the consequence never fired
+        assertNull( results.get( "fired" ) );
+    }
+
+    public void testFocusStack() throws ConsequenceException {
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        // create the consequence
+        final Consequence consequence = new Consequence() {
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory workingMemory) {
+                // do nothing
+            }
+        };
+
+        final ReteTuple tuple = new ReteTuple( new DefaultFactHandle( 1,
+                                                                      "cheese" ) );
+
+        // create a rule for each agendaGroup
+        final Rule rule0 = new Rule( "test-rule0" );
+        final RuleTerminalNode node0 = new RuleTerminalNode( 3,
+                                                             new MockTupleSource( 2 ),
+                                                             rule0,
+                                                             rule0.getLhs(),
+                                                             buildContext );
+        rule0.setConsequence( consequence );
+        final PropagationContext context0 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule0,
+                                                                        null );
+
+        final Rule rule1 = new Rule( "test-rule1",
+                                     "agendaGroup1" );
+        final RuleTerminalNode node1 = new RuleTerminalNode( 5,
+                                                             new MockTupleSource( 4 ),
+                                                             rule1,
+                                                             rule1.getLhs(),
+                                                             buildContext );
+        rule1.setConsequence( consequence );
+        final PropagationContext context1 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule1,
+                                                                        null );
+
+        final Rule rule2 = new Rule( "test-rule2",
+                                     "agendaGroup2" );
+        final RuleTerminalNode node2 = new RuleTerminalNode( 7,
+                                                             new MockTupleSource( 6 ),
+                                                             rule2,
+                                                             rule2.getLhs(),
+                                                             buildContext );
+        rule2.setConsequence( consequence );
+        final PropagationContext context2 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule2,
+                                                                        null );
+
+        final Rule rule3 = new Rule( "test-rule3",
+                                     "agendaGroup3" );
+        final RuleTerminalNode node3 = new RuleTerminalNode( 9,
+                                                             new MockTupleSource( 8 ),
+                                                             rule3,
+                                                             rule3.getLhs(),
+                                                             buildContext );
+        rule3.setConsequence( consequence );
+        final PropagationContext context3 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule3,
+                                                                        null );
+        
+        final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+        // create the AgendaGroups
+        final AgendaGroup agendaGroup1 = new BinaryHeapQueueAgendaGroup( "agendaGroup1", ruleBase );
+        agenda.addAgendaGroup( agendaGroup1 );
+
+        final AgendaGroup agendaGroup2 = new BinaryHeapQueueAgendaGroup( "agendaGroup2", ruleBase );
+        agenda.addAgendaGroup( agendaGroup2 );
+
+        final AgendaGroup agendaGroup3 = new BinaryHeapQueueAgendaGroup( "agendaGroup3", ruleBase );
+        agenda.addAgendaGroup( agendaGroup3 );        
+
+        // focus at this point is MAIN
+        assertEquals( 0,
+                      agenda.focusStackSize() );
+
+        node0.assertTuple( tuple,
+                           context0,
+                           workingMemory );
+
+        // check focus is main
+        final AgendaGroup main = agenda.getAgendaGroup( AgendaGroup.MAIN );
+        assertEquals( agenda.getFocus(),
+                      main );
+        // check main got the tuple
+        assertEquals( 1,
+                      agenda.getFocus().size() );
+        node2.assertTuple( tuple,
+                           context2,
+                           workingMemory );
+
+        // main is still focus and this tuple went to agendaGroup 2
+        assertEquals( 1,
+                      agenda.getFocus().size() );
+
+        // check agendaGroup2 still got the tuple
+        assertEquals( 1,
+                      agendaGroup2.size() );
+
+        // make sure total agenda size reflects this
+        assertEquals( 2,
+                      agenda.agendaSize() );
+
+        // put another one on agendaGroup 2
+        node2.assertTuple( tuple,
+                           context2,
+                           workingMemory );
+
+        // main is still focus so shouldn't have increased
+        assertEquals( 1,
+                      agenda.getFocus().size() );
+
+        // check agendaGroup2 still got the tuple
+        assertEquals( 2,
+                      agendaGroup2.size() );
+
+        // make sure total agenda size reflects this
+        assertEquals( 3,
+                      agenda.agendaSize() );
+
+        // set the focus to agendaGroup1, note agendaGroup1 has no activations
+        agenda.setFocus( "agendaGroup1" );
+        // add agendaGroup2 onto the focus stack
+        agenda.setFocus( "agendaGroup2" );
+        // finally add agendaGroup3 to the top of the focus stack
+        agenda.setFocus( "agendaGroup3" );
+
+        // agendaGroup3, the current focus, has no activations
+        assertEquals( 0,
+                      agenda.getFocus().size() );
+
+        // add to agendaGroup 3
+        node3.assertTuple( tuple,
+                           context3,
+                           workingMemory );
+
+        assertEquals( 1,
+                      agenda.getFocus().size() );
+
+        node3.assertTuple( tuple,
+                           context3,
+                           workingMemory );
+
+        // agendaGroup3 now has 2 activations
+        assertEquals( 2,
+                      agenda.getFocus().size() );
+        // check totalAgendaSize still works
+        assertEquals( 5,
+                      agenda.agendaSize() );
+
+        // ok now lets check that stacks work with fireNextItem
+        agenda.fireNextItem( null );
+
+        // agendaGroup3 should still be the current agendaGroup
+        assertEquals( agenda.getFocus(),
+                      agendaGroup3 );
+        // agendaGroup3 has gone from 2 to one activations
+        assertEquals( 1,
+                      agenda.getFocus().size() );
+        // check totalAgendaSize has reduced too
+        assertEquals( 4,
+                      agenda.agendaSize() );
+
+        // now repeat the process
+        agenda.fireNextItem( null );
+
+        // focus is still agendaGroup3, but now its empty
+        assertEquals( agenda.getFocus(),
+                      agendaGroup3 );
+        assertEquals( 0,
+                      agenda.getFocus().size() );
+        assertEquals( 3,
+                      agenda.agendaSize() );
+
+        // repeat fire again
+        agenda.fireNextItem( null );
+
+        // agendaGroup3 is empty so it should be popped from the stack making````````````````````
+        // agendaGroup2
+        // the current agendaGroup
+        assertEquals( agendaGroup2,
+                      agenda.getFocus() );
+        // agendaGroup2 had 2 activations, now it only has 1
+        assertEquals( 1,
+                      agenda.getFocus().size() );
+        assertEquals( 2,
+                      agenda.agendaSize() );
+
+        // repeat fire again
+        agenda.fireNextItem( null );
+
+        assertEquals( agenda.getFocus(),
+                      agendaGroup2 );
+        assertEquals( 0,
+                      agenda.getFocus().size() );
+        assertEquals( 1,
+                      agenda.agendaSize() );
+
+        // this last fire is more interesting as it demonstrates that
+        // agendaGroup1 on
+        // the stack before agendaGroup2 gets skipped as it has no activations
+        agenda.fireNextItem( null );
+
+        assertEquals( agenda.getFocus(),
+                      main );
+        assertEquals( 0,
+                      agenda.getFocus().size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+
+    }
+
+    //
+    public void testAutoFocus() throws ConsequenceException {
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+        final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+        // create the agendaGroup
+        final AgendaGroup agendaGroup = new BinaryHeapQueueAgendaGroup( "agendaGroup", ruleBase );
+        agenda.addAgendaGroup( agendaGroup );
+
+        // create the consequence
+        final Consequence consequence = new Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory workingMemory) {
+                // do nothing
+            }
+        };
+
+        final ReteTuple tuple = new ReteTuple( new DefaultFactHandle( 1,
+                                                                      "cheese" ) );
+
+        // create a rule for the agendaGroup
+        final Rule rule = new Rule( "test-rule",
+                                    "agendaGroup" );
+        final RuleTerminalNode node = new RuleTerminalNode( 2,
+                                                            new MockTupleSource( 2 ),
+                                                            rule,
+                                                            rule.getLhs(),
+                                                            buildContext );
+        rule.setConsequence( consequence );
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       rule,
+                                                                       null );
+
+        // first test that autoFocus=false works. Here the rule should not fire
+        // as its agendaGroup does not have focus.
+        rule.setAutoFocus( false );
+
+        node.assertTuple( tuple,
+                          context,
+                          workingMemory );
+
+        // check activation as added to the agendaGroup
+        assertEquals( 1,
+                      agendaGroup.size() );
+
+        // fire next item, agendaGroup should not fire as its not on the focus stack
+        // and thus should retain its sinle activation
+        agenda.fireNextItem( null );
+        assertEquals( 1,
+                      agendaGroup.size() );
+
+        // Clear the agenda we we can test again
+        agenda.clearAgenda();
+        assertEquals( 0,
+                      agendaGroup.size() );
+
+        // Now test that autoFocus=true works. Here the rule should fire as its
+        // agendaGroup gets the focus when the activation is created.
+        rule.setAutoFocus( true );
+
+        node.assertTuple( tuple,
+                          context,
+                          workingMemory );
+
+        assertEquals( 1,
+                      agendaGroup.size() );
+        agenda.fireNextItem( null );
+        assertEquals( 0,
+                      agendaGroup.size() );
+    }
+
+    public void testAgendaGroupLockOnActive() {
+        final InternalRuleBase ruleBase = ( InternalRuleBase ) RuleBaseFactory.newRuleBase();
+
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+        final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+        // create the agendaGroup
+        final InternalAgendaGroup agendaGroup = new BinaryHeapQueueAgendaGroup( "agendaGroup", ruleBase );
+        agenda.addAgendaGroup( agendaGroup );
+
+        final ReteTuple tuple = new ReteTuple( new DefaultFactHandle( 1,
+                                                                      "cheese" ) );
+
+        // create a rule for the agendaGroup
+        final Rule rule = new Rule( "test-rule",
+                                    "agendaGroup" );
+        final RuleTerminalNode node = new RuleTerminalNode( 2,
+                                                            new MockTupleSource( 2 ),
+                                                            rule,
+                                                            rule.getLhs(),
+                                                            buildContext );
+
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       rule,
+                                                                       null );
+
+        // When both the rule is lock-on-active and the agenda group is active, activations should be ignored
+        rule.setLockOnActive( true );
+        agendaGroup.setActive( true );
+        node.assertTuple( tuple,
+                          context,
+                          workingMemory );
+        // activation should be ignored
+        assertEquals( 0,
+                      agendaGroup.size() );
+
+        // lock-on-active is now false so activation should propagate
+        rule.setLockOnActive( false );
+        node.assertTuple( tuple,
+                          context,
+                          workingMemory );
+        assertEquals( 1,
+                      agendaGroup.size() );
+
+        // even if lock-on-active is true, unless the agenda group is active the activation will still propagate
+        rule.setLockOnActive( true );
+        agendaGroup.setActive( false );
+        node.assertTuple( tuple,
+                          context,
+                          workingMemory );
+        assertEquals( 2,
+                      agendaGroup.size() );
+    }
+
+    public void testActivationGroup() {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+        final List list = new ArrayList();
+
+        // create the consequence
+        final Consequence consequence = new Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory workingMemory) {
+                list.add( knowledgeHelper.getRule() );
+            }
+        };
+
+        final ReteTuple tuple = new ReteTuple( new DefaultFactHandle( 1,
+                                                                      "cheese" ) );
+
+        // create a rule for each agendaGroup
+        final Rule rule0 = new Rule( "test-rule0" );
+        rule0.setActivationGroup( "activation-group-0" );
+        final RuleTerminalNode node0 = new RuleTerminalNode( 3,
+                                                             new MockTupleSource( 2 ),
+                                                             rule0,
+                                                             rule0.getLhs(),
+                                                             buildContext );
+        rule0.setConsequence( consequence );
+        final PropagationContext context0 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule0,
+                                                                        null );
+
+        final Rule rule1 = new Rule( "test-rule1" );
+        rule1.setActivationGroup( "activation-group-0" );
+        final RuleTerminalNode node1 = new RuleTerminalNode( 5,
+                                                             new MockTupleSource( 4 ),
+                                                             rule1,
+                                                             rule1.getLhs(),
+                                                             buildContext );
+        rule1.setConsequence( consequence );
+        final PropagationContext context1 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule1,
+                                                                        null );
+
+        final Rule rule2 = new Rule( "test-rule2" );
+        final RuleTerminalNode node2 = new RuleTerminalNode( 7,
+                                                             new MockTupleSource( 6 ),
+                                                             rule2,
+                                                             rule2.getLhs(),
+                                                             buildContext );
+        rule2.setConsequence( consequence );
+        final PropagationContext context2 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule2,
+                                                                        null );
+
+        final Rule rule3 = new Rule( "test-rule3",
+                                     "agendaGroup3" );
+        rule3.setActivationGroup( "activation-group-3" );
+        final RuleTerminalNode node3 = new RuleTerminalNode( 9,
+                                                             new MockTupleSource( 8 ),
+                                                             rule3,
+                                                             rule3.getLhs(),
+                                                             buildContext );
+        rule3.setConsequence( consequence );
+        final PropagationContext context3 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule3,
+                                                                        null );
+
+        // Assert the tuple and check it was added to activation-group-0
+        node0.assertTuple( tuple,
+                           context0,
+                           workingMemory );
+        final ActivationGroup activationGroup0 = agenda.getActivationGroup( "activation-group-0" );
+        assertEquals( 1,
+                      activationGroup0.size() );
+
+        // Removing a tuple should remove the activation from the activation-group-0 again
+        node0.retractTuple( tuple,
+                            context0,
+                            workingMemory );
+        assertEquals( 0,
+                      activationGroup0.size() );
+
+        // Assert the tuple again and check it was added to activation-group-0
+        node0.assertTuple( tuple,
+                           context0,
+                           workingMemory );
+        assertEquals( 1,
+                      activationGroup0.size() );
+
+        // Assert another tuple and check it was added to activation-group-0        
+        node1.assertTuple( tuple,
+                           context1,
+                           workingMemory );
+        assertEquals( 2,
+                      activationGroup0.size() );
+
+        // There should now be two potential activations to fire
+        assertEquals( 2,
+                      agenda.focusStackSize() );
+
+        // The first tuple should fire, adding itself to the List and clearing and cancelling the other Activations in the activation-group-0        
+        agenda.fireNextItem( null );
+
+        // Make sure the activation-group-0 is clear
+        assertEquals( 0,
+                      activationGroup0.size() );
+
+        // Make sure the Agenda  is  empty
+        assertEquals( 0,
+                      agenda.focusStackSize() );
+
+        // List should only have a single item, "rule0"
+        assertEquals( 1,
+                      list.size() );
+        assertSame( rule0,
+                    list.get( 0 ) );
+
+        list.clear();
+
+        //-------------------
+        // Now try a more complex scenario involving  two Xor Groups and one  rule not in a Group
+        node0.assertTuple( tuple,
+                           context0,
+                           workingMemory );
+        node1.assertTuple( tuple,
+                           context1,
+                           workingMemory );
+        node2.assertTuple( tuple,
+                           context2,
+                           workingMemory );
+        node3.assertTuple( tuple,
+                           context3,
+                           workingMemory );
+
+        // activation-group-0 should be populated again
+        assertEquals( 2,
+                      activationGroup0.size() );
+
+        // make sure the activation-group-3 is cleared when we can clear the Agenda Group for the activation that is in both
+        final ActivationGroup activationGroup3 = agenda.getActivationGroup( "activation-group-3" );
+
+        assertEquals( 4,
+                      agenda.agendaSize() );
+        assertEquals( 1,
+                      activationGroup3.size() );
+
+        agenda.clearAgendaGroup( "agendaGroup3" );
+        assertEquals( 3,
+                      agenda.agendaSize() );
+        assertEquals( 0,
+                      activationGroup3.size() );
+
+        // Activation for activation-group-0 should be next - the activation in no activation/agenda group should remain on the agenda
+        agenda.fireNextItem( null );
+        assertEquals( 1,
+                      agenda.agendaSize() );
+        assertEquals( 0,
+                      activationGroup0.size() );
+
+        // Fire  the  last activation and  make sure the Agenda Empties
+        agenda.fireNextItem( null );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+
+        assertEquals( 2,
+                      list.size() );
+        assertEquals( rule0,
+                      list.get( 0 ) );
+        assertEquals( rule2,
+                      list.get( 1 ) );
+
+    }
+
+    /** 
+     * Basic RuleFlowGroup test where there are three rules, each in their own
+     * RuleFlowGroup.  First only rule-flow-group-0 is activated and rule0 is
+     * executed.  When the two remaining groups are activated, the rule with the
+     * highest priority is executed first.
+     */
+    public void testRuleFlowGroup() {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+        final List list = new ArrayList();
+
+        // create the consequence
+        final Consequence consequence = new Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory workingMemory) {
+                list.add( knowledgeHelper.getRule() );
+            }
+        };
+
+        // create a rule for each rule flow groups
+        final Rule rule0 = new Rule( "test-rule0" );
+        rule0.setRuleFlowGroup( "rule-flow-group-0" );
+        rule0.setConsequence( consequence );
+
+        final RuleTerminalNode node0 = new RuleTerminalNode( 3,
+                                                             new MockTupleSource( 2 ),
+                                                             rule0,
+                                                             rule0.getLhs(),
+                                                             buildContext );
+
+        final Rule rule1 = new Rule( "test-rule1" );
+        rule1.setRuleFlowGroup( "rule-flow-group-1" );
+        rule1.setConsequence( consequence );
+
+        final RuleTerminalNode node1 = new RuleTerminalNode( 4,
+                                                             new MockTupleSource( 2 ),
+                                                             rule1,
+                                                             rule1.getLhs(),
+                                                             buildContext );
+
+        final Rule rule2 = new Rule( "test-rule2" );
+        rule2.setRuleFlowGroup( "rule-flow-group-2" );
+        rule2.setConsequence( consequence );
+        rule2.setSalience( new SalienceInteger( 10 ) );
+
+        final RuleTerminalNode node2 = new RuleTerminalNode( 5,
+                                                             new MockTupleSource( 2 ),
+                                                             rule2,
+                                                             rule2.getLhs(),
+                                                             buildContext );
+
+        final PropagationContext context0 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule0,
+                                                                        null );
+
+        final RuleFlowGroup ruleFlowGroup0 = agenda.getRuleFlowGroup( "rule-flow-group-0" );
+        final RuleFlowGroup ruleFlowGroup1 = agenda.getRuleFlowGroup( "rule-flow-group-1" );
+        final RuleFlowGroup ruleFlowGroup2 = agenda.getRuleFlowGroup( "rule-flow-group-2" );
+
+        final ReteTuple tuple0 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+        node0.assertTuple( tuple0,
+                           context0,
+                           workingMemory );
+
+        final ReteTuple tuple1 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+        node0.assertTuple( tuple1,
+                           context0,
+                           workingMemory );
+
+        final ReteTuple tuple2 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+        node1.assertTuple( tuple2,
+                           context0,
+                           workingMemory );
+
+        final ReteTuple tuple3 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+        node2.assertTuple( tuple3,
+                           context0,
+                           workingMemory );
+
+        // RuleFlowGroups should be populated, but the agenda shouldn't be
+        assertEquals( 2,
+                      ruleFlowGroup0.size() );
+        assertEquals( 1,
+                      ruleFlowGroup1.size() );
+        assertEquals( 1,
+                      ruleFlowGroup2.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+
+        // Activate the RuleFlowGroup, the nodes stay in the group, but should now also be in the Agenda
+        agenda.activateRuleFlowGroup( "rule-flow-group-0" );
+        assertEquals( 2,
+                      ruleFlowGroup0.size() );
+        assertEquals( 2,
+                      agenda.agendaSize() );
+
+        // As we fire each rule they are removed from both the Agenda and the RuleFlowGroup
+        agenda.fireNextItem( null );
+        assertEquals( 1,
+                      ruleFlowGroup0.size() );
+        assertEquals( 1,
+                      agenda.agendaSize() );
+
+        // After firing all activations of RuleFlowGroup 0, the agenda is empty
+        agenda.fireNextItem( null );
+        assertEquals( 0,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+
+        // Now we activate two RuleFlowGroups together
+        // All their activations should be added to the agenda.
+        agenda.activateRuleFlowGroup( "rule-flow-group-1" );
+        agenda.activateRuleFlowGroup( "rule-flow-group-2" );
+        assertEquals( 1,
+                      ruleFlowGroup1.size() );
+        assertEquals( 1,
+                      ruleFlowGroup2.size() );
+        assertEquals( 2,
+                      agenda.agendaSize() );
+
+        // we set the salience higher on rule2, so it sould fire first and empty ruleFlowGroup2
+        agenda.fireNextItem( null );
+        assertEquals( 1,
+                      ruleFlowGroup1.size() );
+        assertEquals( 0,
+                      ruleFlowGroup2.size() );
+        assertEquals( 1,
+                      agenda.agendaSize() );
+
+        // this is the last activation, so everything should be empty after this
+        agenda.fireNextItem( null );
+        assertEquals( 0,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      ruleFlowGroup1.size() );
+        assertEquals( 0,
+                      ruleFlowGroup2.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+    }
+
+    /**
+     * RuleFlowGroup test that makes sure that, if new activations are created
+     * for an active RuleFlowGroup, those activations get added to the agenda
+     * directly as well.
+     */
+    public void testRuleFlowGroup1() {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+        // create rule1
+        final Consequence consequence1 = new Consequence() {
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory workingMemory) {
+                // do nothing
+            }
+        };
+
+        final Rule rule1 = new Rule( "test-rule1" );
+        rule1.setRuleFlowGroup( "rule-flow-group-0" );
+        rule1.setConsequence( consequence1 );
+
+        final RuleTerminalNode node1 = new RuleTerminalNode( 4,
+                                                             new MockTupleSource( 2 ),
+                                                             rule1,
+                                                             rule1.getLhs(),
+                                                             buildContext );
+
+        // create context
+        final PropagationContext context0 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule1,
+                                                                        null );
+
+        // create rule0
+        final Consequence consequence0 = new Consequence() {
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory w) {
+                // activate rule1
+                final ReteTuple tuple1 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                               "cheese" ) );
+                node1.assertTuple( tuple1,
+                                   context0,
+                                   workingMemory );
+            }
+        };
+
+        final Rule rule0 = new Rule( "test-rule0" );
+        rule0.setRuleFlowGroup( "rule-flow-group-0" );
+        rule0.setConsequence( consequence0 );
+
+        final RuleTerminalNode node0 = new RuleTerminalNode( 3,
+                                                             new MockTupleSource( 2 ),
+                                                             rule0,
+                                                             rule0.getLhs(),
+                                                             buildContext );
+
+        final RuleFlowGroup ruleFlowGroup0 = agenda.getRuleFlowGroup( "rule-flow-group-0" );
+
+        // Create one activation for rule0 only
+        final ReteTuple tuple0 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+        node0.assertTuple( tuple0,
+                           context0,
+                           workingMemory );
+
+        // RuleFlowGroup should be populated, but the agenda shouldn't be
+        assertEquals( 1,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+
+        // Activate the RuleFlowGroup, the activation stays in the group, but should now also be in the Agenda
+        agenda.activateRuleFlowGroup( "rule-flow-group-0" );
+        assertEquals( 1,
+                      ruleFlowGroup0.size() );
+        assertEquals( 1,
+                      agenda.agendaSize() );
+
+        // As we fire the rule, an new activation is created for rule1, and it should be added to group AND the agenda. 
+        agenda.fireNextItem( null );
+        assertEquals( 1,
+                      ruleFlowGroup0.size() );
+        assertEquals( 1,
+                      agenda.agendaSize() );
+
+        // After firing all activations of RuleFlowGroup 0, the agenda is empty
+        agenda.fireNextItem( null );
+        assertEquals( 0,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+    }
+
+    /**
+     * RuleFlowGroup test that makes sure that, if an activation in an active
+     * RuleFlowGroup gets deactivated, the activation is no longer executed.
+     */
+    public void testRuleFlowGroup2() {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+        // create rule1
+        final Consequence consequence1 = new Consequence() {
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory workingMemory) {
+                // do nothing
+            }
+        };
+
+        final Rule rule1 = new Rule( "test-rule1" );
+        rule1.setRuleFlowGroup( "rule-flow-group-0" );
+        rule1.setConsequence( consequence1 );
+
+        final RuleTerminalNode node1 = new RuleTerminalNode( 4,
+                                                             new MockTupleSource( 2 ),
+                                                             rule1,
+                                                             rule1.getLhs(),
+                                                             buildContext );
+
+        // create context
+        final PropagationContext context0 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule1,
+                                                                        null );
+
+        final ReteTuple tuple1 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+
+        // create rule0
+        final Consequence consequence0 = new Consequence() {
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory w) {
+                // deactivate rule1
+                node1.retractTuple( tuple1,
+                                    context0,
+                                    workingMemory );
+            }
+        };
+
+        final Rule rule0 = new Rule( "test-rule0" );
+        rule0.setRuleFlowGroup( "rule-flow-group-0" );
+        rule0.setConsequence( consequence0 );
+        rule0.setSalience( new SalienceInteger( 10  ) );
+
+        final RuleTerminalNode node0 = new RuleTerminalNode( 3,
+                                                             new MockTupleSource( 2 ),
+                                                             rule0,
+                                                             rule0.getLhs(),
+                                                             buildContext );
+
+        final RuleFlowGroup ruleFlowGroup0 = agenda.getRuleFlowGroup( "rule-flow-group-0" );
+
+        // Create an activation for both rules
+        final ReteTuple tuple0 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+        node0.assertTuple( tuple0,
+                           context0,
+                           workingMemory );
+
+        node1.assertTuple( tuple1,
+                           context0,
+                           workingMemory );
+
+        // RuleFlowGroup should be populated, but the agenda shouldn't be
+        assertEquals( 2,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+
+        // Activate the RuleFlowGroup, the activations stay in the group, but should now also be in the Agenda
+        agenda.activateRuleFlowGroup( "rule-flow-group-0" );
+        assertEquals( 2,
+                      ruleFlowGroup0.size() );
+        assertEquals( 2,
+                      agenda.agendaSize() );
+
+        // As we fire the rule, rule0 should execute first, as it has higher salience.
+        // Rule0 should deactivate rule1 as well, so the everything should be empty
+        agenda.fireNextItem( null );
+        assertEquals( 0,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+
+    }
+
+    /**
+     * RuleFlowGroup test that makes sure that, when deactivating a RuleFlowGroup,
+     * all activations for that group are no longer on the agenda.  When
+     * reactivating the RuleFlowGroup however, they get added to the agenda again. 
+     */
+    public void testRuleFlowGroup3() {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+        // create rule0
+        final Consequence consequence0 = new Consequence() {
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory w) {
+                // do nothing
+            }
+        };
+
+        final Rule rule0 = new Rule( "test-rule0" );
+        rule0.setRuleFlowGroup( "rule-flow-group-0" );
+        rule0.setConsequence( consequence0 );
+
+        final RuleTerminalNode node0 = new RuleTerminalNode( 1,
+                                                             new MockTupleSource( 2 ),
+                                                             rule0,
+                                                             rule0.getLhs(),
+                                                             buildContext );
+
+        final RuleFlowGroup ruleFlowGroup0 = agenda.getRuleFlowGroup( "rule-flow-group-0" );
+
+        // create context
+        final PropagationContext context0 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule0,
+                                                                        null );
+
+        // Create two activation for this rule
+        final ReteTuple tuple0 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+        node0.assertTuple( tuple0,
+                           context0,
+                           workingMemory );
+        final ReteTuple tuple1 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+        node0.assertTuple( tuple1,
+                           context0,
+                           workingMemory );
+
+        // RuleFlowGroup should be populated, but the agenda shouldn't be
+        assertEquals( 2,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+
+        // Activate the RuleFlowGroup, the activations stay in the group, but 
+        // should now also be in the Agenda
+        agenda.activateRuleFlowGroup( "rule-flow-group-0" );
+        assertEquals( 2,
+                      ruleFlowGroup0.size() );
+        assertEquals( 2,
+                      agenda.agendaSize() );
+
+        // Reactivate an already active RuleFlowGroup should not have any effect
+        agenda.activateRuleFlowGroup( "rule-flow-group-0" );
+        assertEquals( 2,
+                      ruleFlowGroup0.size() );
+        assertEquals( 2,
+                      agenda.agendaSize() );
+
+        // Deactivate the RuleFlowGroup, the activations should be removed from
+        // the agenda but still in the RuleFlowGroup
+        agenda.deactivateRuleFlowGroup( "rule-flow-group-0" );
+        assertEquals( 2,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+
+        // Reactivate the RuleFlowGroup, the activations stay in the group, but 
+        // should now also be in the Agenda again
+        agenda.activateRuleFlowGroup( "rule-flow-group-0" );
+        assertEquals( 2,
+                      ruleFlowGroup0.size() );
+        assertEquals( 2,
+                      agenda.agendaSize() );
+
+    }
+
+    /**
+     * Test auto-deactivation of RuleFlowGroup. 
+     */
+    public void testRuleFlowGroup4() {
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
+        final InternalWorkingMemory workingMemory = ( InternalWorkingMemory ) ruleBase.newStatefulSession();                ;
+
+        final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+        // create rule0
+        final Consequence consequence0 = new Consequence() {
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory w) {
+                // do nothing
+            }
+        };
+
+        final Rule rule0 = new Rule( "test-rule0" );
+        rule0.setRuleFlowGroup( "rule-flow-group-0" );
+        rule0.setConsequence( consequence0 );
+
+        final RuleTerminalNode node0 = new RuleTerminalNode( idGenerator.getNextId(),
+                                                             new MockTupleSource( idGenerator.getNextId() ),
+                                                             rule0,
+                                                             rule0.getLhs(),
+                                                             buildContext );
+
+        final RuleFlowGroup ruleFlowGroup0 = agenda.getRuleFlowGroup( "rule-flow-group-0" );
+        assertTrue( ruleFlowGroup0.isAutoDeactivate() );
+        ruleFlowGroup0.setAutoDeactivate( false );
+        assertFalse( ruleFlowGroup0.isAutoDeactivate() );
+
+        // create context
+        final PropagationContext context0 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule0,
+                                                                        null );
+
+        // Create an activation for this rule
+        final ReteTuple tuple0 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+        node0.assertTuple( tuple0,
+                           context0,
+                           workingMemory );
+
+        // RuleFlowGroup should be populated, but the agenda shouldn't be
+        assertEquals( 1,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+
+        // Activate the RuleFlowGroup, the activations stay in the group, but 
+        // should now also be in the Agenda
+        agenda.activateRuleFlowGroup( "rule-flow-group-0" );
+        assertEquals( 1,
+                      ruleFlowGroup0.size() );
+        assertEquals( 1,
+                      agenda.agendaSize() );
+
+        // Execute activation
+        agenda.fireNextItem( null );
+        assertEquals( 0,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+        assertTrue( ruleFlowGroup0.isActive() );
+
+        // Set auto-deactivation status to true
+        ruleFlowGroup0.setAutoDeactivate( true );
+        assertTrue( ruleFlowGroup0.isAutoDeactivate() );
+        assertFalse( ruleFlowGroup0.isActive() );
+
+        // Add another activation and activate RuleFlowGroup again
+        final ReteTuple tuple1 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+        node0.assertTuple( tuple1,
+                           context0,
+                           workingMemory );
+        agenda.activateRuleFlowGroup( "rule-flow-group-0" );
+        assertEquals( 1,
+                      ruleFlowGroup0.size() );
+        assertEquals( 1,
+                      agenda.agendaSize() );
+        assertTrue( ruleFlowGroup0.isActive() );
+
+        // Execute the activation, the RuleFlowGroup should automatically deactivate
+        agenda.fireNextItem( null );
+        assertEquals( 0,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+        workingMemory.executeQueuedActions();
+        assertFalse( ruleFlowGroup0.isActive() );
+
+        // A new activation should now be added to the RuleFlowGroup but not to the agenda 
+        final ReteTuple tuple2 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+        node0.assertTuple( tuple2,
+                           context0,
+                           workingMemory );
+        assertEquals( 1,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+    }
+    
+    /**
+     * Test auto-deactivation of empty ruleflow group. 
+     */
+    public void testRuleFlowGroup5() {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+        // create rule0
+        final Consequence consequence0 = new Consequence() {
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory w) {
+                // do nothing
+            }
+        };
+
+        final Rule rule0 = new Rule( "test-rule0" );
+        rule0.setRuleFlowGroup( "rule-flow-group-0" );
+        rule0.setConsequence( consequence0 );
+
+        final RuleFlowGroup ruleFlowGroup0 = agenda.getRuleFlowGroup( "rule-flow-group-0" );
+        assertTrue( ruleFlowGroup0.isAutoDeactivate() );
+
+        // RuleFlowGroup should be empty, as well as the agenda
+        assertEquals( 0,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+
+        // Activate the RuleFlowGroup, the activations stay in the group, but 
+        // should now also be in the Agenda
+        agenda.activateRuleFlowGroup( "rule-flow-group-0" );
+        assertEquals( 0,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+        workingMemory.executeQueuedActions();
+
+        assertFalse( ruleFlowGroup0.isActive() );
+    }
+
+    public void testRuleFlowGroupLockOnActive() {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+        final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+        // create the agendaGroup
+        //final AgendaGroupImpl agendaGroup = new AgendaGroupImpl( "agendaGroup" );
+        //agenda.addAgendaGroup( agendaGroup );
+
+        final RuleFlowGroupImpl ruleFlowGroup = (RuleFlowGroupImpl) agenda.getRuleFlowGroup( "rule-flow-group-0" );
+
+        final ReteTuple tuple = new ReteTuple( new DefaultFactHandle( 1,
+                                                                      "cheese" ) );
+
+        // create a rule for the agendaGroup
+        final Rule rule = new Rule( "test-rule" );
+        rule.setRuleFlowGroup( "rule-flow-group-0" );
+        final RuleTerminalNode node = new RuleTerminalNode( 2,
+                                                            new MockTupleSource( 2 ),
+                                                            rule,
+                                                            rule.getLhs(),
+                                                            buildContext );
+
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       rule,
+                                                                       null );
+
+        // When both the rule is lock-on-active and the agenda group is active, activations should be ignored
+        rule.setLockOnActive( true );
+        ruleFlowGroup.setAutoDeactivate( false );
+        ruleFlowGroup.setActive( true );
+        node.assertTuple( tuple,
+                          context,
+                          workingMemory );
+        // activation should be ignored
+        assertEquals( 0,
+                      ruleFlowGroup.size() );
+
+        // lock-on-active is now false so activation should propagate
+        rule.setLockOnActive( false );
+        node.assertTuple( tuple,
+                          context,
+                          workingMemory );
+        assertEquals( 1,
+                      ruleFlowGroup.size() );
+
+        // even if lock-on-active is true, unless the agenda group is active the activation will still propagate
+        rule.setLockOnActive( true );
+        ruleFlowGroup.setActive( false );
+        node.assertTuple( tuple,
+                          context,
+                          workingMemory );
+        assertEquals( 2,
+                      ruleFlowGroup.size() );
+    }
+    
+    public void testSequentialAgenda() {
+        RuleBaseConfiguration conf = new RuleBaseConfiguration();
+        conf.setSequential( true );
+        InternalRuleBase ruleBase = ( InternalRuleBase ) RuleBaseFactory.newRuleBase( conf );
+        
+
+        // create the consequence
+        final Consequence consequence = new Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory workingMemory) {
+                // do nothing
+            }
+        };
+
+        final ReteTuple tuple = new ReteTuple( new DefaultFactHandle( 1,
+                                                                      "cheese" ) );
+
+        // create a rule for each agendaGroup
+        final Rule rule0 = new Rule( "test-rule0" );
+        final RuleTerminalNode node0 = new RuleTerminalNode( 3,
+                                                             new MockTupleSource( 2 ),
+                                                             rule0,
+                                                             rule0.getLhs(),
+                                                             buildContext );
+        node0.setSequence( 72 );
+        rule0.setConsequence( consequence );
+        final PropagationContext context0 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule0,
+                                                                        null );
+
+        final Rule rule1 = new Rule( "test-rule1",
+                                     "agendaGroup1" );
+        final RuleTerminalNode node1 = new RuleTerminalNode( 5,
+                                                             new MockTupleSource( 4 ),
+                                                             rule1,
+                                                             rule1.getLhs(),
+                                                             buildContext );
+        node1.setSequence( 10 );
+        rule1.setConsequence( consequence );
+        final PropagationContext context1 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule1,
+                                                                        null );
+
+        final Rule rule2 = new Rule( "test-rule2",
+                                     "agendaGroup1" );
+        final RuleTerminalNode node2 = new RuleTerminalNode( 7,
+                                                             new MockTupleSource( 6 ),
+                                                             rule2,
+                                                             rule2.getLhs(),
+                                                             buildContext );
+        node2.setSequence( 7 );
+        rule2.setConsequence( consequence );
+        final PropagationContext context2 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule2,
+                                                                        null );
+
+        final Rule rule3 = new Rule( "test-rule3",
+                                     "agendaGroup2" );
+        final RuleTerminalNode node3 = new RuleTerminalNode( 9,
+                                                             new MockTupleSource( 8 ),
+                                                             rule3,
+                                                             rule3.getLhs(),
+                                                             buildContext );
+        node3.setSequence( 0 );
+        rule3.setConsequence( consequence );
+        final PropagationContext context3 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule3,
+                                                                        null );
+        
+        ruleBase.getAgendaGroupRuleTotals().put( "MAIN", new Integer( 100 ) );
+        ruleBase.getAgendaGroupRuleTotals().put( "agendaGroup1", new Integer( 10 ) );
+        ruleBase.getAgendaGroupRuleTotals().put( "agendaGroup2", new Integer( 1 ) );
+
+        InternalWorkingMemory workingMemory = new ReteooWorkingMemory(0, ruleBase);
+
+        final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+        final AgendaGroup agendaGroup1 = new ArrayAgendaGroup( "agendaGroup1", ruleBase );
+        agenda.addAgendaGroup( agendaGroup1 );
+
+        final AgendaGroup agendaGroup2 = new ArrayAgendaGroup( "agendaGroup2", ruleBase );
+        agenda.addAgendaGroup( agendaGroup2 );  
+        
+        // focus at this point is MAIN
+        assertEquals( 0,
+                      agenda.focusStackSize() );
+
+        node0.assertTuple( tuple,
+                           context0,
+                           workingMemory );
+
+        // check focus is main
+        final AgendaGroup main = agenda.getAgendaGroup( AgendaGroup.MAIN );
+        assertEquals( agenda.getFocus(),
+                      main );
+        // check main got the tuple
+        assertEquals( 1,
+                      agenda.getFocus().size() );
+        node2.assertTuple( tuple,
+                           context2,
+                           workingMemory );
+
+        // main is still focus and this tuple went to agendaGroup1
+        assertEquals( 1,
+                      agenda.getFocus().size() );
+
+        // check agendaGroup1 still got the tuple
+        assertEquals( 1,
+                      agendaGroup1.size() );
+
+        // make sure total agenda size reflects this
+        assertEquals( 2,
+                      agenda.agendaSize() );
+
+        // put another one on agendaGroup 1
+        node2.assertTuple( tuple,
+                           context2,
+                           workingMemory );
+
+        // main is still focus so shouldn't have increased
+        assertEquals( 1,
+                      agenda.getFocus().size() );
+
+        // check agendaGroup2 still got the tuple
+        assertEquals( 2,
+                      agendaGroup1.size() );
+
+        // make sure total agenda size reflects this
+        assertEquals( 3,
+                      agenda.agendaSize() );
+
+        // set the focus to agendaGroup1, note agendaGroup1 has no activations
+        agenda.setFocus( "agendaGroup1" );
+        // add agendaGroup2 onto the focus stack
+        agenda.setFocus( "agendaGroup2" );
+
+        // agendaGroup2, the current focus, has no activations
+        assertEquals( 0,
+                      agenda.getFocus().size() );
+
+        // add to agendaGroup2
+        node3.assertTuple( tuple,
+                           context3,
+                           workingMemory );
+
+        assertEquals( 1,
+                      agenda.getFocus().size() );
+
+        node3.assertTuple( tuple,
+                           context3,
+                           workingMemory );
+
+        // agendaGroup2 now has 2 activations
+        assertEquals( 2,
+                      agenda.getFocus().size() );
+        
+        // check totalAgendaSize still works
+        assertEquals( 5,
+                      agenda.agendaSize() );
+
+        // ok now lets check that stacks work with fireNextItem
+        agenda.fireNextItem( null );
+
+        // agendaGroup2 should still be the current agendaGroup
+        assertEquals( agendaGroup2,
+                      agenda.getFocus() );
+        // agendaGroup2 has gone from 2 to one activations
+        assertEquals( 1,
+                      agenda.getFocus().size() );
+        // check totalAgendaSize has reduced too
+        assertEquals( 4,
+                      agenda.agendaSize() );
+
+        // now repeat the process
+        agenda.fireNextItem( null );
+
+        // focus is still agendaGroup2, but now its empty
+        assertEquals( agendaGroup2, agenda.getFocus() );
+        assertEquals( 0,
+                      agenda.getFocus().size() );
+        assertEquals( 3,
+                      agenda.agendaSize() );
+
+        // repeat fire again
+        agenda.fireNextItem( null );
+
+        // agendaGroup2 is empty so it should be popped from the stack making agendaGroup1 the current agendaGroup
+        assertEquals( agendaGroup1,
+                      agenda.getFocus() );
+        // agendaGroup1 had 2 activations, now it only has 1
+        assertEquals( 1,
+                      agenda.getFocus().size() );
+        assertEquals( 2,
+                      agenda.agendaSize() );
+
+        // repeat fire again
+        agenda.fireNextItem( null );
+
+        assertEquals( agendaGroup1,
+                      agenda.getFocus() );
+        assertEquals( 0,
+                      agenda.getFocus().size() );
+        assertEquals( 1,
+                      agenda.agendaSize() );
+
+        // this last fire is more interesting as it demonstrates that
+        // agendaGroup1 on
+        // the stack before agendaGroup2 gets skipped as it has no activations
+        agenda.fireNextItem( null );
+
+        assertEquals( agenda.getFocus(),
+                      main );
+        assertEquals( 0,
+                      agenda.getFocus().size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );        
+        
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/AlphaNodeTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/AlphaNodeTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/AlphaNodeTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,798 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.beans.IntrospectionException;
+
+import org.drools.Cheese;
+import org.drools.DroolsTestCase;
+import org.drools.FactException;
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuleBaseFactory;
+import org.drools.base.ClassFieldExtractor;
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.FieldFactory;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.EqualityEvaluatorsDefinition;
+import org.drools.base.evaluators.Operator;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.PropagationContextImpl;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.LiteralConstraint;
+import org.drools.rule.Rule;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.FieldValue;
+import org.drools.spi.PropagationContext;
+import org.drools.util.FactHashTable;
+
+public class AlphaNodeTest extends DroolsTestCase {
+
+    ClassFieldExtractorCache cache = ClassFieldExtractorCache.getInstance();
+    EqualityEvaluatorsDefinition equals = new EqualityEvaluatorsDefinition();
+
+    public void testMemory() {
+        RuleBaseConfiguration config = new RuleBaseConfiguration();
+        config.setAlphaMemory( false );
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase( config );
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator() );
+        ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final AlphaNode alphaNode = new AlphaNode( buildContext.getNextId(),
+                                                   null,
+                                                   null,
+                                                   buildContext );
+
+        final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( alphaNode );
+
+        assertNotNull( memory );
+    }
+
+    public void testLiteralConstraintAssertObjectWithMemory() throws Exception {
+        RuleBaseConfiguration config = new RuleBaseConfiguration();
+        config.setAlphaMemory( true );
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase( config );
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator() );
+        ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final Rule rule = new Rule( "test-rule" );
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+
+        final MockObjectSource source = new MockObjectSource( buildContext.getNextId() );
+
+        final ClassFieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                                  "type",
+                                                                  getClass().getClassLoader() );
+
+        final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
+
+        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE, Operator.EQUAL );
+        final LiteralConstraint constraint = new LiteralConstraint( extractor,
+                                                                    evaluator,
+                                                                    field );
+
+        // With Memory
+        buildContext.setAlphaNodeMemoryAllowed( true );
+        final AlphaNode alphaNode = new AlphaNode( buildContext.getNextId(),
+                                                   constraint,
+                                                   source,
+                                                   buildContext ); // has memory
+
+        final MockObjectSink sink = new MockObjectSink();
+        alphaNode.addObjectSink( sink );
+
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           5 );
+        final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory.insert( cheddar );
+
+        // check sink is empty
+        assertLength( 0,
+                      sink.getAsserted() );
+
+        // check alpha memory is empty 
+        final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( alphaNode );
+
+        assertEquals( 0,
+                      memory.size() );
+
+        // object should assert as it passes text
+        alphaNode.assertObject( f0,
+                                context,
+                                workingMemory );
+
+        assertEquals( 1,
+                      sink.getAsserted().size() );
+        assertEquals( 1,
+                      memory.size() );
+        Object[] list = (Object[]) sink.getAsserted().get( 0 );
+        assertSame( cheddar,
+                    workingMemory.getObject( (DefaultFactHandle) list[0] ) );
+        assertTrue( "Should contain 'cheddar handle'",
+                    memory.contains( f0 ) );
+
+        final Cheese stilton = new Cheese( "stilton",
+                                           6 );
+        final DefaultFactHandle f1 = new DefaultFactHandle( 1,
+                                                            stilton );
+
+        // object should NOT assert as it does not pass test
+        alphaNode.assertObject( f1,
+                                context,
+                                workingMemory );
+
+        assertLength( 1,
+                      sink.getAsserted() );
+        assertEquals( 1,
+                      memory.size() );
+        list = (Object[]) sink.getAsserted().get( 0 );
+        assertSame( cheddar,
+                    workingMemory.getObject( (DefaultFactHandle) list[0] ) );
+        assertTrue( "Should contain 'cheddar handle'",
+                    memory.contains( f0 ) );
+    }
+
+    public void testIsMemoryAllowedOverride() throws Exception {
+        RuleBaseConfiguration config = new RuleBaseConfiguration();
+        config.setAlphaMemory( true );
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase( config );
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator() );
+        ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final Rule rule = new Rule( "test-rule" );
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+
+        final MockObjectSource source = new MockObjectSource( buildContext.getNextId() );
+
+        final ClassFieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                                  "type",
+                                                                  getClass().getClassLoader() );
+
+        final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
+
+        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE, Operator.EQUAL );
+        final LiteralConstraint constraint = new LiteralConstraint( extractor,
+                                                                    evaluator,
+                                                                    field );
+
+        // With Memory
+        buildContext.setAlphaNodeMemoryAllowed( false );
+        final AlphaNode alphaNode = new AlphaNode( buildContext.getNextId(),
+                                                   constraint,
+                                                   source,
+                                                   buildContext ); // has memory
+
+        final MockObjectSink sink = new MockObjectSink();
+        alphaNode.addObjectSink( sink );
+
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           5 );
+        final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory.insert( cheddar );
+
+        // check sink is empty
+        assertLength( 0,
+                      sink.getAsserted() );
+
+        // check alpha memory is empty 
+        final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( alphaNode );
+
+        assertEquals( 0,
+                      memory.size() );
+
+        // object should assert as it passes text
+        alphaNode.assertObject( f0,
+                                context,
+                                workingMemory );
+
+        assertEquals( 1,
+                      sink.getAsserted().size() );
+        // memory should be one, as even though isAlphaMemory is on for the configuration, the build never allows memory
+        assertEquals( 0,
+                      memory.size() );
+    }
+
+    public void testLiteralConstraintAssertObjectWithoutMemory() throws Exception {
+        RuleBaseConfiguration config = new RuleBaseConfiguration();
+        config.setAlphaMemory( false );
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase( config );
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator() );
+        ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final Rule rule = new Rule( "test-rule" );
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+
+        final MockObjectSource source = new MockObjectSource( buildContext.getNextId() );
+
+        final ClassFieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                                  "type",
+                                                                  getClass().getClassLoader() );
+
+        final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
+
+        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE, Operator.EQUAL );
+        final LiteralConstraint constraint = new LiteralConstraint( extractor,
+                                                                    evaluator,
+                                                                    field );
+
+        // With Memory
+        final AlphaNode alphaNode = new AlphaNode( buildContext.getNextId(),
+                                                   constraint,
+                                                   source,
+                                                   buildContext ); // no memory
+
+        final MockObjectSink sink = new MockObjectSink();
+        alphaNode.addObjectSink( sink );
+
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           5 );
+        final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory.insert( cheddar );
+
+        // check sink is empty
+        assertLength( 0,
+                      sink.getAsserted() );
+
+        // check alpha memory is empty 
+        final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( alphaNode );
+
+        assertEquals( 0,
+                      memory.size() );
+
+        // object should assert as it passes text
+        alphaNode.assertObject( f0,
+                                context,
+                                workingMemory );
+
+        assertEquals( 1,
+                      sink.getAsserted().size() );
+        assertEquals( 0,
+                      memory.size() );
+        Object[] list = (Object[]) sink.getAsserted().get( 0 );
+        assertSame( cheddar,
+                    workingMemory.getObject( (DefaultFactHandle) list[0] ) );
+        assertFalse( "Should not contain 'cheddar handle'",
+                     memory.contains( f0 ) );
+
+        final Cheese stilton = new Cheese( "stilton",
+                                           6 );
+        final DefaultFactHandle f1 = new DefaultFactHandle( 1,
+                                                            stilton );
+
+        // object should NOT assert as it does not pass test
+        alphaNode.assertObject( f1,
+                                context,
+                                workingMemory );
+
+        assertLength( 1,
+                      sink.getAsserted() );
+        assertEquals( 0,
+                      memory.size() );
+        list = (Object[]) sink.getAsserted().get( 0 );
+        assertSame( cheddar,
+                    workingMemory.getObject( (DefaultFactHandle) list[0] ) );
+        assertFalse( "Should not contain 'cheddar handle'",
+                     memory.contains( f0 ) );
+    }
+
+    public void testLiteralConstraintAssertSequentialMode() throws Exception {
+        RuleBaseConfiguration config = new RuleBaseConfiguration();
+        config.setSequential( true );
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase( config );
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator() );
+        ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( buildContext.getNextId(),
+                                                                     ruleBase );
+
+        final Rule rule = new Rule( "test-rule" );
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+
+        final MockObjectSource source = new MockObjectSource( buildContext.getNextId() );
+
+        final ClassFieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                                  "type",
+                                                                  getClass().getClassLoader() );
+
+        final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
+
+        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE, Operator.EQUAL );
+        final LiteralConstraint constraint = new LiteralConstraint( extractor,
+                                                                    evaluator,
+                                                                    field );
+
+        // With Memory
+        final AlphaNode alphaNode = new AlphaNode( buildContext.getNextId(),
+                                                   constraint,
+                                                   source,
+                                                   buildContext ); // has memory
+
+        final MockObjectSink sink = new MockObjectSink();
+        alphaNode.addObjectSink( sink );
+
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           5 );
+        final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory.insert( cheddar );
+
+        // check sink is empty
+        assertLength( 0,
+                      sink.getAsserted() );
+
+        // check alpha memory is empty 
+        final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( alphaNode );
+
+        assertEquals( 0,
+                      memory.size() );
+
+        // object should assert as it passes text
+        alphaNode.assertObject( f0,
+                                context,
+                                workingMemory );
+
+        assertEquals( 1,
+                      sink.getAsserted().size() );
+        assertEquals( 0,
+                      memory.size() );
+        Object[] list = (Object[]) sink.getAsserted().get( 0 );
+        assertSame( cheddar,
+                    workingMemory.getObject( (DefaultFactHandle) list[0] ) );
+
+        final Cheese stilton = new Cheese( "stilton",
+                                           6 );
+        final DefaultFactHandle f1 = new DefaultFactHandle( 1,
+                                                            stilton );
+
+        // object should NOT assert as it does not pass test
+        alphaNode.assertObject( f1,
+                                context,
+                                workingMemory );
+
+        assertLength( 1,
+                      sink.getAsserted() );
+        assertEquals( 0,
+                      memory.size() );
+        list = (Object[]) sink.getAsserted().get( 0 );
+        assertSame( cheddar,
+                    workingMemory.getObject( (DefaultFactHandle) list[0] ) );
+    }
+
+    /*
+     * dont need to test with and without memory on this, as it was already done
+     * on the previous two tests. This just test AlphaNode With a different
+     * Constraint type.
+     */
+    public void testReturnValueConstraintAssertObject() throws Exception {
+        RuleBaseConfiguration config = new RuleBaseConfiguration();
+        config.setAlphaMemory( false );
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase( config );
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator() );
+        ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final Rule rule = new Rule( "test-rule" );
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+
+        final MockObjectSource source = new MockObjectSource( buildContext.getNextId() );
+
+        final FieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                             "type",
+                                                             getClass().getClassLoader() );
+
+        final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
+
+        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE, Operator.EQUAL );
+        final LiteralConstraint constraint = new LiteralConstraint( extractor,
+                                                                    evaluator,
+                                                                    field );
+
+        final AlphaNode alphaNode = new AlphaNode( buildContext.getNextId(),
+                                                   constraint,
+                                                   source,
+                                                   buildContext );
+        final MockObjectSink sink = new MockObjectSink();
+        alphaNode.addObjectSink( sink );
+
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           5 );
+
+        final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory.insert( cheddar );
+
+        assertLength( 0,
+                      sink.getAsserted() );
+
+        // object should assert as it passes text
+        alphaNode.assertObject( f0,
+                                context,
+                                workingMemory );
+
+        assertLength( 1,
+                      sink.getAsserted() );
+        final Object[] list = (Object[]) sink.getAsserted().get( 0 );
+        assertSame( cheddar,
+                    workingMemory.getObject( (DefaultFactHandle) list[0] ) );
+
+        final Cheese stilton = new Cheese( "stilton",
+                                           6 );
+        f0.setObject( stilton );
+
+        sink.getAsserted().clear();
+
+        // object should not assert as it does not pass text
+        alphaNode.assertObject( f0,
+                                context,
+                                workingMemory );
+
+        assertLength( 0,
+                      sink.getAsserted() );
+    }
+
+    public void testRetractObjectWithMemory() throws Exception {
+        RuleBaseConfiguration config = new RuleBaseConfiguration();
+        config.setAlphaMemory( true );
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase( config );
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator() );
+        ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final Rule rule = new Rule( "test-rule" );
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+
+        final MockObjectSource source = new MockObjectSource( buildContext.getNextId() );
+
+        final FieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                             "type",
+                                                             getClass().getClassLoader() );
+
+        final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
+
+        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE, Operator.EQUAL );
+        final LiteralConstraint constraint = new LiteralConstraint( extractor,
+                                                                    evaluator,
+                                                                    field );
+
+        buildContext.setAlphaNodeMemoryAllowed( true );
+        final AlphaNode alphaNode = new AlphaNode( buildContext.getNextId(),
+                                                   constraint,
+                                                   source,
+                                                   buildContext ); // has memory
+        final MockObjectSink sink = new MockObjectSink();
+        alphaNode.addObjectSink( sink );
+
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           5 );
+
+        final DefaultFactHandle f0 = new DefaultFactHandle( 0,
+                                                            cheddar );
+
+        // check alpha memory is empty
+        final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( alphaNode );
+        assertEquals( 0,
+                      memory.size() );
+
+        // object should assert as it passes text
+        alphaNode.assertObject( f0,
+                                context,
+                                workingMemory );
+
+        assertEquals( 1,
+                      memory.size() );
+
+        final DefaultFactHandle f1 = new DefaultFactHandle( 1,
+                                                            "cheese" );
+
+        // object should NOT retract as it doesn't exist
+        alphaNode.retractObject( f1,
+                                 context,
+                                 workingMemory );
+
+        assertLength( 0,
+                      sink.getRetracted() );
+        assertEquals( 1,
+                      memory.size() );
+        assertTrue( "Should contain 'cheddar handle'",
+                    memory.contains( f0 ) );
+
+        // object should retract as it does exist
+        alphaNode.retractObject( f0,
+                                 context,
+                                 workingMemory );
+
+        assertLength( 1,
+                      sink.getRetracted() );
+        assertEquals( 0,
+                      memory.size() );
+        final Object[] list = (Object[]) sink.getRetracted().get( 0 );
+        assertSame( f0,
+                    list[0] );
+
+    }
+
+    public void testRetractObjectWithoutMemory() throws Exception {
+        RuleBaseConfiguration config = new RuleBaseConfiguration();
+        config.setAlphaMemory( false );
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase( config );
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator() );
+        ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final Rule rule = new Rule( "test-rule" );
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+
+        final MockObjectSource source = new MockObjectSource( buildContext.getNextId() );
+
+        final FieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                             "type",
+                                                             getClass().getClassLoader() );
+
+        final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
+
+        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE, Operator.EQUAL );
+        final LiteralConstraint constraint = new LiteralConstraint( extractor,
+                                                                    evaluator,
+                                                                    field );
+
+        final AlphaNode alphaNode = new AlphaNode( buildContext.getNextId(),
+                                                   constraint,
+                                                   source,
+                                                   buildContext ); // no memory
+        final MockObjectSink sink = new MockObjectSink();
+        alphaNode.addObjectSink( sink );
+
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           5 );
+
+        final DefaultFactHandle f0 = new DefaultFactHandle( 0,
+                                                            cheddar );
+
+        // check alpha memory is empty
+        final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( alphaNode );
+        assertEquals( 0,
+                      memory.size() );
+
+        // object should assert as it passes text
+        alphaNode.assertObject( f0,
+                                context,
+                                workingMemory );
+
+        assertEquals( 0,
+                      memory.size() );
+
+        final DefaultFactHandle f1 = new DefaultFactHandle( 1,
+                                                            new Cheese( "brie",
+                                                                        10 ) );
+
+        // object should NOT retract as it doesn't exist
+        alphaNode.retractObject( f1,
+                                 context,
+                                 workingMemory );
+
+        // without memory, it will always propagate a retract
+        assertLength( 0,
+                      sink.getRetracted() );
+        assertEquals( 0,
+                      memory.size() );
+        assertFalse( "Should not contain 'cheddar handle'",
+                     memory.contains( f0 ) );
+
+        // object should retract as it does exist
+        alphaNode.retractObject( f0,
+                                 context,
+                                 workingMemory );
+
+        assertLength( 1,
+                      sink.getRetracted() );
+        assertEquals( 0,
+                      memory.size() );
+        final Object[] list = (Object[]) sink.getRetracted().get( 0 );
+        assertSame( f0,
+                    list[0] );
+
+    }
+
+    public void testUpdateSinkWithMemory() throws FactException,
+                                          IntrospectionException {
+        // An AlphaNode with memory should not try and repropagate from its source
+        // Also it should only update the latest tuple sinky
+        RuleBaseConfiguration config = new RuleBaseConfiguration();
+        config.setAlphaMemory( true );
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase( config );
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator() );
+        ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final Rule rule = new Rule( "test-rule" );
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+
+        final MockObjectSource source = new MockObjectSource( buildContext.getNextId() );
+
+        final FieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                             "type",
+                                                             getClass().getClassLoader() );
+
+        final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
+
+        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE, Operator.EQUAL );
+        final LiteralConstraint constraint = new LiteralConstraint( extractor,
+                                                                    evaluator,
+                                                                    field );
+
+        buildContext.setAlphaNodeMemoryAllowed( true );
+        final AlphaNode alphaNode = new AlphaNode( buildContext.getNextId(),
+                                                   constraint,
+                                                   source,
+                                                   buildContext ); // has memory
+
+        alphaNode.attach();
+
+        final MockObjectSink sink1 = new MockObjectSink();
+        alphaNode.addObjectSink( sink1 );
+
+        // Assert a single fact which should be in the AlphaNode memory and also
+        // propagated to the
+        // the tuple sink
+        final Cheese cheese = new Cheese( "cheddar",
+                                          0 );
+        final DefaultFactHandle handle1 = new DefaultFactHandle( 1,
+                                                                 cheese );
+
+        alphaNode.assertObject( handle1,
+                                context,
+                                workingMemory );
+
+        // Create a fact that should not be propagated, since the alpha node restriction will filter it out
+        final Cheese stilton = new Cheese( "stilton",
+                                           10 );
+        final DefaultFactHandle handle2 = new DefaultFactHandle( 2,
+                                                                 stilton );
+        // adding handle to the mock source
+        source.addFact( handle2 );
+
+        alphaNode.assertObject( handle2,
+                                context,
+                                workingMemory );
+        assertLength( 1,
+                      sink1.getAsserted() );
+
+        // Attach a new tuple sink
+        final MockObjectSink sink2 = new MockObjectSink();
+
+        // Tell the alphanode to update the new node. Make sure the first sink1
+        // is not updated
+        // likewise the source should not do anything
+        alphaNode.updateSink( sink2,
+                              context,
+                              workingMemory );
+
+        assertLength( 1,
+                      sink1.getAsserted() );
+        assertLength( 1,
+                      sink2.getAsserted() );
+        assertEquals( 0,
+                      source.getUdated() );
+    }
+
+    public void testUpdateSinkWithoutMemory() throws FactException,
+                                             IntrospectionException {
+        // An AlphaNode without memory should try and repropagate from its source
+        RuleBaseConfiguration config = new RuleBaseConfiguration();
+        config.setAlphaMemory( false );
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase( config );
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator() );
+        ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final Rule rule = new Rule( "test-rule" );
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+
+        final MockObjectSource source = new MockObjectSource( buildContext.getNextId() );
+
+        final FieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                             "type",
+                                                             getClass().getClassLoader() );
+
+        final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
+
+        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE, Operator.EQUAL );
+        final LiteralConstraint constraint = new LiteralConstraint( extractor,
+                                                                    evaluator,
+                                                                    field );
+
+        final AlphaNode alphaNode = new AlphaNode( buildContext.getNextId(),
+                                                   constraint,
+                                                   source,
+                                                   buildContext ); // no memory
+
+        alphaNode.attach();
+
+        final MockObjectSink sink1 = new MockObjectSink();
+        alphaNode.addObjectSink( sink1 );
+
+        // Assert a single fact which should be in the AlphaNode memory and also
+        // propagated to the
+        // the tuple sink
+        final Cheese cheese = new Cheese( "cheddar",
+                                          0 );
+        final DefaultFactHandle handle1 = new DefaultFactHandle( 1,
+                                                                 cheese );
+        // adding handle to the mock source
+        source.addFact( handle1 );
+
+        alphaNode.assertObject( handle1,
+                                context,
+                                workingMemory );
+
+        // Create a fact that should not be propagated, since the alpha node restriction will filter it out
+        final Cheese stilton = new Cheese( "stilton",
+                                           10 );
+        final DefaultFactHandle handle2 = new DefaultFactHandle( 2,
+                                                                 stilton );
+        // adding handle to the mock source
+        source.addFact( handle2 );
+
+        alphaNode.assertObject( handle2,
+                                context,
+                                workingMemory );
+
+        assertLength( 1,
+                      sink1.getAsserted() );
+
+        // Attach a new tuple sink
+        final MockObjectSink sink2 = new MockObjectSink();
+
+        // Tell the alphanode to update the new node. Make sure the first sink1
+        // is not updated
+        // likewise the source should not do anything
+        alphaNode.updateSink( sink2,
+                              context,
+                              workingMemory );
+
+        assertLength( 1,
+                      sink1.getAsserted() );
+        assertLength( 1,
+                      sink2.getAsserted() );
+        assertEquals( 1,
+                      source.getUdated() );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/BaseNodeTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/BaseNodeTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/BaseNodeTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,76 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import junit.framework.TestCase;
+
+import org.drools.common.BaseNode;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+
+public class BaseNodeTest extends TestCase {
+
+    public void testBaseNode() {
+        MockBaseNode node = new MockBaseNode( 10 );
+        assertEquals( 10,
+                      node.getId() );
+
+        node = new MockBaseNode( 155 );
+        assertEquals( 155,
+                      node.getId() );
+    }
+
+    class MockBaseNode extends BaseNode {
+        /**
+         * 
+         */
+        private static final long serialVersionUID = 400L;
+
+        public MockBaseNode(final int id) {
+            super( id );
+        }
+
+        public void ruleAttached() {
+            // TODO Auto-generated method stub
+
+        }
+
+        public void attach() {
+            // TODO Auto-generated method stub
+
+        }
+
+        public void updateNewNode(final InternalWorkingMemory workingMemory,
+                                  final PropagationContext context) {
+            // TODO Auto-generated method stub
+
+        }
+
+        public void remove(ReteooBuilder builder,
+                           final BaseNode node, final InternalWorkingMemory[] workingMemories) {
+            // TODO Auto-generated method stub
+
+        }
+
+        public void attach(final InternalWorkingMemory[] workingMemories) {
+            // TODO Auto-generated method stub
+
+        }
+
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/BetaNodeTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/BetaNodeTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/BetaNodeTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2006 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;
+
+import org.drools.RuleBaseFactory;
+import org.drools.common.EmptyBetaConstraints;
+import org.drools.reteoo.builder.BuildContext;
+
+import junit.framework.TestCase;
+
+/**
+ * @author etirelli
+ *
+ */
+public class BetaNodeTest extends TestCase {
+
+    /* (non-Javadoc)
+     * @see junit.framework.TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    /* (non-Javadoc)
+     * @see junit.framework.TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * Test method for {@link org.drools.reteoo.BetaNode#equals(java.lang.Object)}.
+     */
+    public void testEqualsObject() {
+        final TupleSource ts = new MockTupleSource( 1 );
+        final ObjectSource os = new MockObjectSource( 2 );
+
+        ReteooRuleBase ruleBase = ( ReteooRuleBase ) RuleBaseFactory.newRuleBase();
+        BuildContext buildContext = new BuildContext( ruleBase, ruleBase.getReteooBuilder().getIdGenerator() );        
+        
+        final BetaNode j1 = new JoinNode( 1,
+                                          ts,
+                                          os,
+                                          EmptyBetaConstraints.getInstance(),
+                                          buildContext );
+        final BetaNode j2 = new JoinNode( 2,
+                                          ts,
+                                          os,
+                                          EmptyBetaConstraints.getInstance(),
+                                          buildContext );
+        final BetaNode n1 = new NotNode( 3,
+                                         ts,
+                                         os,
+                                         EmptyBetaConstraints.getInstance(),
+                                         buildContext );
+        final BetaNode n2 = new NotNode( 4,
+                                         ts,
+                                         os,
+                                         EmptyBetaConstraints.getInstance(),
+                                         buildContext );
+
+        assertEquals( j1,
+                      j1 );
+        assertEquals( j2,
+                      j2 );
+        assertEquals( j1,
+                      j2 );
+        assertEquals( n1,
+                      n1 );
+        assertEquals( n2,
+                      n2 );
+        assertEquals( n1,
+                      n2 );
+
+        assertFalse( j1.equals( n1 ) );
+        assertFalse( j1.equals( n2 ) );
+        assertFalse( n1.equals( j1 ) );
+        assertFalse( n1.equals( j2 ) );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/CollectNodeTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/CollectNodeTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/CollectNodeTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,437 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.reteoo;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+import junit.framework.Assert;
+
+import org.drools.DroolsTestCase;
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuleBaseFactory;
+import org.drools.base.ClassObjectType;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.EmptyBetaConstraints;
+import org.drools.common.PropagationContextImpl;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.Collect;
+import org.drools.rule.Pattern;
+import org.drools.rule.Rule;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.MockConstraint;
+import org.drools.spi.ObjectType;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
+
+/**
+ * @author etirelli
+ *
+ */
+public class CollectNodeTest extends DroolsTestCase {
+    Rule                rule;
+    PropagationContext  contextAssert;
+    PropagationContext  contextRetract;
+    ReteooWorkingMemory workingMemory;
+    MockObjectSource    objectSource;
+    MockTupleSource     tupleSource;
+    MockTupleSink       sink;
+    BetaNode            node;
+    BetaMemory          memory;
+    MockConstraint      constraint = new MockConstraint();
+    Collect             collect;
+
+    /* (non-Javadoc)
+     * @see junit.framework.TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+        super.setUp();
+        this.rule = new Rule( "test-rule" );
+        this.contextAssert = new PropagationContextImpl( 0,
+                                                         PropagationContext.ASSERTION,
+                                                         null,
+                                                         null );
+        this.contextRetract = new PropagationContextImpl( 0,
+                                                         PropagationContext.RETRACTION,
+                                                         null,
+                                                         null );
+
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ruleBase.getReteooBuilder().getIdGenerator() );
+        
+        this.workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        this.tupleSource = new MockTupleSource( 4 );
+        this.objectSource = new MockObjectSource( 4 );
+        this.sink = new MockTupleSink();
+
+        final ObjectType srcObjType = new ClassObjectType( String.class );
+        final Pattern sourcePattern = new Pattern( 0,
+                                                srcObjType );
+        final ObjectType resultObjType = new ClassObjectType( LinkedList.class );
+        final Pattern resultPattern = new Pattern( 1,
+                                                resultObjType );
+        this.collect = new Collect( sourcePattern,
+                                    resultPattern );
+
+        this.node = new CollectNode( 15,
+                                     this.tupleSource,
+                                     this.objectSource,
+                                     new AlphaNodeFieldConstraint[0],
+                                     EmptyBetaConstraints.getInstance(),
+                                     EmptyBetaConstraints.getInstance(),
+                                     this.collect,
+                                     false,
+                                     buildContext );
+
+        this.node.addTupleSink( this.sink );
+
+        this.memory = (BetaMemory) this.workingMemory.getNodeMemory( this.node );
+
+        // check memories are empty
+        assertEquals( 0,
+                      this.memory.getTupleMemory().size() );
+        assertEquals( 0,
+                      this.memory.getFactHandleMemory().size() );
+    }
+
+    /* (non-Javadoc)
+     * @see junit.framework.TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    public void testUpdateNewNode() {
+        this.node.updateSink( this.sink,
+                              this.contextAssert,
+                              this.workingMemory );
+        Assert.assertEquals( "No tuple should be propagated",
+                             0,
+                             this.sink.getAsserted().size() );
+
+        this.node.assertTuple( new ReteTuple( this.workingMemory.getFactHandleFactory().newFactHandle( "cheese", false, null ) ),
+                               this.contextAssert,
+                               this.workingMemory );
+        this.node.assertTuple( new ReteTuple( this.workingMemory.getFactHandleFactory().newFactHandle( "other cheese", false, null ) ),
+                               this.contextAssert,
+                               this.workingMemory );
+
+        Assert.assertEquals( "Two tuples should have been propagated",
+                             2,
+                             this.sink.getAsserted().size() );
+
+        final MockTupleSink otherSink = new MockTupleSink();
+
+        this.node.addTupleSink( otherSink );
+        this.node.updateSink( otherSink,
+                              this.contextAssert,
+                              this.workingMemory );
+
+        Assert.assertEquals( "Two tuples should have been propagated",
+                             2,
+                             otherSink.getAsserted().size() );
+    }
+
+    public void testAssertTuple() {
+        final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.getFactHandleFactory().newFactHandle( "cheese", false, null );
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        // assert tuple, should add one to left memory
+        this.node.assertTuple( tuple0,
+                               this.contextAssert,
+                               this.workingMemory );
+        // check memories 
+        assertEquals( 1,
+                      this.memory.getTupleMemory().size() );
+        assertEquals( 0,
+                      this.memory.getFactHandleMemory().size() );
+        Assert.assertTrue( "An empty collection should be propagated",
+                           ((Collection) ((DefaultFactHandle) ((Tuple) ((Object[]) this.sink.getAsserted().get( 0 ))[0]).get( 1 )).getObject()).isEmpty() );
+
+        // assert tuple, should add left memory 
+        final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.getFactHandleFactory().newFactHandle( "other cheese", false, null );
+
+        final ReteTuple tuple1 = new ReteTuple( f1 );
+        this.node.assertTuple( tuple1,
+                               this.contextAssert,
+                               this.workingMemory );
+        assertEquals( 2,
+                      this.memory.getTupleMemory().size() );
+        Assert.assertTrue( "An empty collection should be propagated",
+                           ((Collection) ((DefaultFactHandle) ((Tuple) ((Object[]) this.sink.getAsserted().get( 1 ))[0]).get( 1 )).getObject()).isEmpty() );
+
+        assertTrue( this.memory.getTupleMemory().contains( tuple0 ) );
+        assertTrue( this.memory.getTupleMemory().contains( tuple1 ) );
+
+        Assert.assertEquals( "Two tuples should have been propagated",
+                             2,
+                             this.sink.getAsserted().size() );
+    }
+
+    public void testAssertTupleWithObjects() {
+        final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.getFactHandleFactory().newFactHandle( "cheese", false, null );
+        final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.getFactHandleFactory().newFactHandle( "other cheese", false, null );
+
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        this.node.assertObject( f0,
+                                this.contextAssert,
+                                this.workingMemory );
+        this.node.assertObject( f1,
+                                this.contextAssert,
+                                this.workingMemory );
+
+        // assert tuple, should add one to left memory
+        this.node.assertTuple( tuple0,
+                               this.contextAssert,
+                               this.workingMemory );
+        // check memories 
+        assertEquals( 1,
+                      this.memory.getTupleMemory().size() );
+        assertEquals( 2,
+                      this.memory.getFactHandleMemory().size() );
+        Assert.assertEquals( "Wrong number of elements in matching objects list ",
+                             2,
+                             ((Collection) ((DefaultFactHandle) ((Tuple) ((Object[]) this.sink.getAsserted().get( 0 ))[0]).get( 1 )).getObject()).size() );
+
+        // assert tuple, should add left memory 
+        final ReteTuple tuple1 = new ReteTuple( f1 );
+        this.node.assertTuple( tuple1,
+                               this.contextAssert,
+                               this.workingMemory );
+        assertEquals( 2,
+                      this.memory.getTupleMemory().size() );
+        Assert.assertEquals( "Wrong number of elements in matching objects list ",
+                             2,
+                             ((Collection) ((DefaultFactHandle) ((Tuple) ((Object[]) this.sink.getAsserted().get( 1 ))[0]).get( 1 )).getObject()).size() );
+
+        assertTrue( this.memory.getTupleMemory().contains( tuple0 ) );
+        assertTrue( this.memory.getTupleMemory().contains( tuple1 ) );
+
+        Assert.assertEquals( "Two tuples should have been propagated",
+                             2,
+                             this.sink.getAsserted().size() );
+    }
+
+    public void testRetractTuple() {
+        final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.getFactHandleFactory().newFactHandle( "cheese", false, null );
+
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        // assert tuple, should add one to left memory
+        this.node.assertTuple( tuple0,
+                               this.contextAssert,
+                               this.workingMemory );
+        // check memories 
+        assertEquals( 1,
+                      this.memory.getTupleMemory().size() );
+        assertEquals( 0,
+                      this.memory.getFactHandleMemory().size() );
+        Assert.assertTrue( "An empty collection should be propagated",
+                           ((Collection) ((DefaultFactHandle) ((Tuple) ((Object[]) this.sink.getAsserted().get( 0 ))[0]).get( 1 )).getObject()).isEmpty() );
+
+        this.node.retractTuple( tuple0,
+                                this.contextRetract,
+                                this.workingMemory );
+        assertEquals( 0,
+                      this.memory.getTupleMemory().size() );
+        assertEquals( 1,
+                      this.sink.getRetracted().size() );
+        assertEquals( 1,
+                      this.sink.getAsserted().size() );
+    }
+
+    public void testAssertObject() {
+        final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.getFactHandleFactory().newFactHandle( "cheese", false, null );
+        final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.getFactHandleFactory().newFactHandle( "other cheese", false, null );
+
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        // assert tuple, should add one to left memory
+        this.node.assertTuple( tuple0,
+                               this.contextAssert,
+                               this.workingMemory );
+
+        // check memory 
+        assertEquals( 1,
+                      this.memory.getTupleMemory().size() );
+        assertEquals( 1,
+                      this.sink.getAsserted().size() );
+        Assert.assertTrue( "An empty collection should be propagated",
+                           ((Collection) ((DefaultFactHandle) ((Tuple) ((Object[]) this.sink.getAsserted().get( 0 ))[0]).get( 1 )).getObject()).isEmpty() );
+
+        this.node.assertObject( f0,
+                                this.contextAssert,
+                                this.workingMemory );
+        assertEquals( 1,
+                      this.memory.getFactHandleMemory().size() );
+        assertEquals( 2,
+                      this.sink.getAsserted().size() );
+        Assert.assertEquals( "Wrong number of elements in matching objects list ",
+                             1,
+                             ((Collection) ((DefaultFactHandle) ((Tuple) ((Object[]) this.sink.getAsserted().get( 1 ))[0]).get( 1 )).getObject()).size() );
+
+        this.node.assertObject( f1,
+                                this.contextAssert,
+                                this.workingMemory );
+
+        assertEquals( 2,
+                      this.memory.getFactHandleMemory().size() );
+        assertEquals( 3,
+                      this.sink.getAsserted().size() );
+        Assert.assertEquals( "Wrong number of elements in matching objects list ",
+                             2,
+                             ((Collection) ((DefaultFactHandle) ((Tuple) ((Object[]) this.sink.getAsserted().get( 2 ))[0]).get( 1 )).getObject()).size() );
+
+    }
+
+    public void testRetractObject() {
+        final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.getFactHandleFactory().newFactHandle( "cheese", false, null );
+        final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.getFactHandleFactory().newFactHandle( "other cheese", false, null );
+
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        this.node.assertObject( f0,
+                                this.contextAssert,
+                                this.workingMemory );
+        this.node.assertObject( f1,
+                                this.contextAssert,
+                                this.workingMemory );
+        assertEquals( 2,
+                      this.memory.getFactHandleMemory().size() );
+
+        // assert tuple, should add one to left memory
+        this.node.assertTuple( tuple0,
+                               this.contextAssert,
+                               this.workingMemory );
+
+        // check memory 
+        assertEquals( 1,
+                      this.memory.getTupleMemory().size() );
+        assertEquals( 0,
+                      this.sink.getRetracted().size() );
+        assertEquals( 1,
+                      this.sink.getAsserted().size() );
+        Assert.assertEquals( "Wrong number of elements in matching objects list ",
+                             2,
+                             ((Collection) ((DefaultFactHandle) ((Tuple) ((Object[]) this.sink.getAsserted().get( 0 ))[0]).get( 1 )).getObject()).size() );
+
+        this.node.retractObject( f1,
+                                 this.contextRetract,
+                                 this.workingMemory );
+        assertEquals( 1,
+                      this.memory.getFactHandleMemory().size() );
+        assertEquals( 1,
+                      this.sink.getRetracted().size() );
+        assertEquals( 2,
+                      this.sink.getAsserted().size() );
+        Assert.assertEquals( "Wrong number of elements in matching objects list ",
+                             1,
+                             ((Collection) ((DefaultFactHandle) ((Tuple) ((Object[]) this.sink.getAsserted().get( 1 ))[0]).get( 1 )).getObject()).size() );
+
+        this.node.retractObject( f0,
+                                 this.contextRetract,
+                                 this.workingMemory );
+        assertEquals( 0,
+                      this.memory.getFactHandleMemory().size() );
+        assertEquals( 2,
+                      this.sink.getRetracted().size() );
+        assertEquals( 3,
+                      this.sink.getAsserted().size() );
+        Assert.assertEquals( "Wrong number of elements in matching objects list ",
+                             0,
+                             ((Collection) ((DefaultFactHandle) ((Tuple) ((Object[]) this.sink.getAsserted().get( 2 ))[0]).get( 1 )).getObject()).size() );
+
+    }
+
+    public void testMemory() {
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ruleBase.getReteooBuilder().getIdGenerator() );
+        
+        final ReteooWorkingMemory workingMemory = ( ReteooWorkingMemory ) ruleBase.newStatefulSession();
+
+        final MockObjectSource objectSource = new MockObjectSource( 1 );
+        final MockTupleSource tupleSource = new MockTupleSource( 1 );
+
+        final CollectNode collectNode = new CollectNode( 2,
+                                                         tupleSource,
+                                                         objectSource,
+                                                         new AlphaNodeFieldConstraint[0],
+                                                         EmptyBetaConstraints.getInstance(),
+                                                         EmptyBetaConstraints.getInstance(),
+                                                         this.collect,
+                                                         false,
+                                                         buildContext  );
+
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( collectNode );
+
+        assertNotNull( memory );
+    }
+
+    public void testAssertTupleSequentialMode() {
+        RuleBaseConfiguration conf = new RuleBaseConfiguration();
+        conf.setSequential( true );
+
+        this.workingMemory = new ReteooWorkingMemory( 1,
+                                                      (ReteooRuleBase) RuleBaseFactory.newRuleBase( conf ) );
+        
+        this.memory = (BetaMemory) this.workingMemory.getNodeMemory( this.node );
+        this.node.setTupleMemoryEnabled( false );
+
+        final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.getFactHandleFactory().newFactHandle( "cheese", false, null );
+        final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.getFactHandleFactory().newFactHandle( "other cheese", false, null );
+
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        this.node.assertObject( f0,
+                                this.contextAssert,
+                                this.workingMemory );
+        this.node.assertObject( f1,
+                                this.contextAssert,
+                                this.workingMemory );
+
+        // assert tuple, should not add to left memory, since we are in sequential mode
+        this.node.assertTuple( tuple0,
+                               this.contextAssert,
+                               this.workingMemory );
+        // check memories 
+        assertNull( this.memory.getTupleMemory() );
+        assertEquals( 2,
+                      this.memory.getFactHandleMemory().size() );
+        Assert.assertEquals( "Wrong number of elements in matching objects list ",
+                             2,
+                             ((Collection) ((DefaultFactHandle) ((Tuple) ((Object[]) this.sink.getAsserted().get( 0 ))[0]).get( 1 )).getObject()).size() );
+
+        // assert tuple, should not add to left memory, since we are in sequential mode
+        final ReteTuple tuple1 = new ReteTuple( f1 );
+        this.node.assertTuple( tuple1,
+                               this.contextAssert,
+                               this.workingMemory );
+        assertNull( this.memory.getTupleMemory() );
+        Assert.assertEquals( "Wrong number of elements in matching objects list ",
+                             2,
+                             ((Collection) ((DefaultFactHandle) ((Tuple) ((Object[]) this.sink.getAsserted().get( 1 ))[0]).get( 1 )).getObject()).size() );
+
+        Assert.assertEquals( "Two tuples should have been propagated",
+                             2,
+                             this.sink.getAsserted().size() );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/CompositeObjectSinkAdapterTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/CompositeObjectSinkAdapterTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/CompositeObjectSinkAdapterTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,510 @@
+package org.drools.reteoo;
+
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.drools.Cheese;
+import org.drools.RuleBaseFactory;
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.EqualityEvaluatorsDefinition;
+import org.drools.base.evaluators.Operator;
+import org.drools.base.field.LongFieldImpl;
+import org.drools.base.field.ObjectFieldImpl;
+import org.drools.common.EmptyBetaConstraints;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.LiteralConstraint;
+import org.drools.rule.PredicateConstraint;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.PropagationContext;
+
+public class CompositeObjectSinkAdapterTest extends TestCase {
+    private ReteooRuleBase ruleBase;
+    private BuildContext   buildContext;
+    
+    private EqualityEvaluatorsDefinition equals = new EqualityEvaluatorsDefinition();
+
+    protected void setUp() throws Exception {
+        this.ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        this.buildContext = new BuildContext( ruleBase,
+                                              ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator() );
+    }
+
+    public int    la;
+    public int    blah;
+    public String wah;
+
+    public void testBeta() {
+        final CompositeObjectSinkAdapter ad = new CompositeObjectSinkAdapter();
+        final MockBetaNode beta = new MockBetaNode( buildContext.getNextId(),
+                                                    null,
+                                                    null );
+        ad.addObjectSink( beta );
+        assertEquals( 1,
+                      ad.getSinks().length );
+        assertEquals( beta,
+                      ad.getSinks()[0] );
+
+        assertEquals( 1,
+                      ad.otherSinks.size() );
+        assertEquals( beta,
+                      ad.otherSinks.getFirst() );
+
+        assertNull( ad.hashableSinks );
+        assertNull( ad.hashedFieldIndexes );
+        assertNull( ad.hashedSinkMap );
+
+        ad.removeObjectSink( beta );
+        assertNull( ad.otherSinks );
+        assertEquals( 0,
+                      ad.getSinks().length );
+    }
+
+    public void testAlphaWithPredicate() {
+        final CompositeObjectSinkAdapter ad = new CompositeObjectSinkAdapter();
+        final AlphaNode al = new AlphaNode( buildContext.getNextId(),
+                                            new PredicateConstraint( null,
+                                                                     null ),
+                                            null,
+                                            buildContext );
+        ad.addObjectSink( al );
+
+        assertEquals( 1,
+                      ad.getSinks().length );
+        assertEquals( 1,
+                      ad.otherSinks.size() );
+        assertEquals( al,
+                      ad.otherSinks.getFirst() );
+
+        ad.removeObjectSink( al );
+        assertEquals( 0,
+                      ad.getSinks().length );
+        assertNull( ad.otherSinks );
+
+    }
+
+    public void testSingleAlpha() {
+
+        final CompositeObjectSinkAdapter ad = new CompositeObjectSinkAdapter();
+        final LiteralConstraint lit = new LiteralConstraint( new MockExtractor(),
+                                                             equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ),
+                                                             new ObjectFieldImpl( "stilton" ) );
+        final AlphaNode al = new AlphaNode( buildContext.getNextId(),
+                                            lit,
+                                            new MockObjectSource( 0 ),
+                                            buildContext );
+
+        ad.addObjectSink( al );
+
+        assertNull( ad.otherSinks );
+        assertNotNull( ad.hashedFieldIndexes );
+        assertEquals( 1,
+                      ad.hashableSinks.size() );
+        assertEquals( al,
+                      ad.getSinks()[0] );
+
+        ad.removeObjectSink( al );
+        assertNull( ad.otherSinks );
+        assertNull( ad.hashableSinks );
+
+    }
+
+    public void testDoubleAlphaWithBeta() {
+
+        final CompositeObjectSinkAdapter ad = new CompositeObjectSinkAdapter();
+        final LiteralConstraint lit = new LiteralConstraint( new MockExtractor(),
+                                                             equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ),
+                                                             new ObjectFieldImpl( "stilton" ) );
+        final AlphaNode al = new AlphaNode( buildContext.getNextId(),
+                                            lit,
+                                            new MockObjectSource( 0 ),
+                                            buildContext );
+
+        ad.addObjectSink( al );
+
+        assertNull( ad.otherSinks );
+        assertNotNull( ad.hashedFieldIndexes );
+        assertEquals( 1,
+                      ad.hashableSinks.size() );
+        assertEquals( al,
+                      ad.getSinks()[0] );
+
+        final LiteralConstraint lit2 = new LiteralConstraint( new MockExtractor(),
+                                                              equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ),
+                                                              new ObjectFieldImpl( "cheddar" ) );
+        final AlphaNode al2 = new AlphaNode( buildContext.getNextId(),
+                                             lit2,
+                                             new MockObjectSource( buildContext.getNextId() ),
+                                             buildContext );
+
+        ad.addObjectSink( al2 );
+
+        assertNull( ad.otherSinks );
+        assertEquals( 2,
+                      ad.hashableSinks.size() );
+        assertEquals( al,
+                      ad.getSinks()[0] );
+        assertEquals( al2,
+                      ad.getSinks()[1] );
+
+        //add a beta, just for good measure, make sure it leaves others alone
+        final MockBetaNode beta = new MockBetaNode( buildContext.getNextId(),
+                                                    null,
+                                                    null );
+        ad.addObjectSink( beta );
+        assertNotNull( ad.otherSinks );
+        assertEquals( 2,
+                      ad.hashableSinks.size() );
+
+        assertEquals( 1,
+                      ad.otherSinks.size() );
+        assertEquals( beta,
+                      ad.otherSinks.getFirst() );
+
+        ad.removeObjectSink( beta );
+        assertNull( ad.otherSinks );
+        assertEquals( 2,
+                      ad.hashableSinks.size() );
+
+    }
+
+    public void testTripleAlpha() {
+        final CompositeObjectSinkAdapter ad = new CompositeObjectSinkAdapter();
+        FieldExtractor extractor = ClassFieldExtractorCache.getInstance().getExtractor( Cheese.class,
+                                                                                        "type",
+                                                                                        this.getClass().getClassLoader() );
+        
+        final LiteralConstraint lit = new LiteralConstraint( extractor,
+                                                             equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ),
+                                                             new ObjectFieldImpl( "stilton" ) );
+        final AlphaNode al = new AlphaNode( buildContext.getNextId(),
+                                            lit,
+                                            new MockObjectSource( buildContext.getNextId() ),
+                                            buildContext );
+
+        ad.addObjectSink( al );
+
+        assertNull( ad.otherSinks );
+        assertNotNull( ad.hashedFieldIndexes );
+        assertEquals( 1,
+                      ad.hashableSinks.size() );
+        assertEquals( al,
+                      ad.getSinks()[0] );
+
+        final LiteralConstraint lit2 = new LiteralConstraint( extractor,
+                                                              equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ),
+                                                              new ObjectFieldImpl( "cheddar" ) );
+        final AlphaNode al2 = new AlphaNode( buildContext.getNextId(),
+                                             lit2,
+                                             new MockObjectSource( buildContext.getNextId() ),
+                                             buildContext );
+
+        ad.addObjectSink( al2 );
+
+        assertNull( ad.hashedSinkMap );
+        assertEquals( 2,
+                      ad.hashableSinks.size() );
+
+        final LiteralConstraint lit3 = new LiteralConstraint( extractor,
+                                                              equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ),
+                                                              new ObjectFieldImpl( "stinky" ) );
+        final AlphaNode al3 = new AlphaNode( buildContext.getNextId(),
+                                             lit3,
+                                             new MockObjectSource( buildContext.getNextId() ),
+                                             buildContext );
+        ad.addObjectSink( al3 );
+
+        //this should now be nicely hashed.
+        assertNotNull( ad.hashedSinkMap );
+        assertNull( ad.hashableSinks );
+
+        //now remove one, check the hashing is undone
+        ad.removeObjectSink( al2 );
+        assertNotNull( ad.hashableSinks );
+        assertEquals( 2,
+                      ad.hashableSinks.size() );
+        assertNull( ad.hashedSinkMap );
+
+    }
+
+    public void testTripleAlphaCharacterConstraint() {
+        final CompositeObjectSinkAdapter ad = new CompositeObjectSinkAdapter();
+        FieldExtractor extractor = ClassFieldExtractorCache.getInstance().getExtractor( Cheese.class,
+                                                                                        "charType",
+                                                                                        this.getClass().getClassLoader() );
+        
+        final LiteralConstraint lit = new LiteralConstraint( extractor,
+                                                             equals.getEvaluator( extractor.getValueType(), Operator.EQUAL ),
+                                                             new LongFieldImpl( 65 ) ); // chars are handled as integers
+        final AlphaNode al = new AlphaNode( buildContext.getNextId(),
+                                            lit,
+                                            new MockObjectSource( buildContext.getNextId() ),
+                                            buildContext );
+
+        ad.addObjectSink( al );
+
+        assertNull( ad.otherSinks );
+        assertNotNull( ad.hashedFieldIndexes );
+        assertEquals( 1,
+                      ad.hashableSinks.size() );
+        assertEquals( al,
+                      ad.getSinks()[0] );
+
+        final LiteralConstraint lit2 = new LiteralConstraint( extractor,
+                                                              equals.getEvaluator( extractor.getValueType(), Operator.EQUAL ),
+                                                              new LongFieldImpl( 66 ) );
+        final AlphaNode al2 = new AlphaNode( buildContext.getNextId(),
+                                             lit2,
+                                             new MockObjectSource( buildContext.getNextId() ),
+                                             buildContext );
+
+        ad.addObjectSink( al2 );
+
+        assertNull( ad.hashedSinkMap );
+        assertEquals( 2,
+                      ad.hashableSinks.size() );
+
+        final LiteralConstraint lit3 = new LiteralConstraint( extractor,
+                                                              equals.getEvaluator( extractor.getValueType(), Operator.EQUAL ),
+                                                              new LongFieldImpl( 67 ) );
+        final AlphaNode al3 = new AlphaNode( buildContext.getNextId(),
+                                             lit3,
+                                             new MockObjectSource( buildContext.getNextId() ),
+                                             buildContext );
+        ad.addObjectSink( al3 );
+
+        //this should now be nicely hashed.
+        assertNotNull( ad.hashedSinkMap );
+        assertNull( ad.hashableSinks );
+        
+        // test propagation
+        Cheese cheese = new Cheese();
+        cheese.setCharType( 'B' );
+        CompositeObjectSinkAdapter.HashKey hashKey = new CompositeObjectSinkAdapter.HashKey();
+        
+        // should find this
+        hashKey.setValue( extractor.getIndex(),
+                          cheese,
+                          extractor );
+        ObjectSink sink = (ObjectSink) ad.hashedSinkMap.get( hashKey );
+        assertSame( al2, sink );
+
+        // should not find this one
+        cheese.setCharType( 'X' );
+        hashKey.setValue( extractor.getIndex(),
+                          cheese,
+                          extractor );
+        sink = (ObjectSink) ad.hashedSinkMap.get( hashKey );
+        assertNull( sink );
+
+        //now remove one, check the hashing is undone
+        ad.removeObjectSink( al2 );
+        assertNotNull( ad.hashableSinks );
+        assertEquals( 2,
+                      ad.hashableSinks.size() );
+        assertNull( ad.hashedSinkMap );
+
+    }
+
+    public void testPropagationWithNullValue() {
+
+        final CompositeObjectSinkAdapter ad = new CompositeObjectSinkAdapter();
+        FieldExtractor extractor = ClassFieldExtractorCache.getInstance().getExtractor( Cheese.class,
+                                                                                        "type",
+                                                                                        this.getClass().getClassLoader() );
+        final LiteralConstraint lit1 = new LiteralConstraint( extractor,
+                                                              equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ),
+                                                              new ObjectFieldImpl( "stilton" ) );
+        final AlphaNode al1 = new AlphaNode( buildContext.getNextId(),
+                                             lit1,
+                                             new MockObjectSource( buildContext.getNextId() ),
+                                             buildContext );
+
+        final LiteralConstraint lit2 = new LiteralConstraint( extractor,
+                                                              equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ),
+                                                              new ObjectFieldImpl( "brie" ) );
+        final AlphaNode al2 = new AlphaNode( buildContext.getNextId(),
+                                             lit2,
+                                             new MockObjectSource( buildContext.getNextId() ),
+                                             buildContext );
+
+        final LiteralConstraint lit3 = new LiteralConstraint( extractor,
+                                                              equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ),
+                                                              new ObjectFieldImpl( "muzzarela" ) );
+        final AlphaNode al3 = new AlphaNode( buildContext.getNextId(),
+                                             lit3,
+                                             new MockObjectSource( buildContext.getNextId() ),
+                                             buildContext );
+
+        ad.addObjectSink( al1 );
+        ad.addObjectSink( al2 );
+        ad.addObjectSink( al3 );
+
+        InternalFactHandle handle = new ReteooFactHandleFactory().newFactHandle( new Cheese(), false, null );
+        try {
+            ad.propagateAssertObject( handle,
+                                      null,
+                                      null );
+        } catch ( RuntimeException e ) {
+            fail( "Not supposed to throw any exception: " + e.getMessage() );
+        }
+
+    }
+
+    static class MockExtractor
+        implements
+        FieldExtractor {
+
+        public int getIndex() {
+            //  Auto-generated method stub
+            return 0;
+        }
+
+        public boolean getBooleanValue(InternalWorkingMemory workingMemory,
+                                       final Object object) {
+            //  Auto-generated method stub
+            return false;
+        }
+
+        public byte getByteValue(InternalWorkingMemory workingMemory,
+                                 final Object object) {
+            //  Auto-generated method stub
+            return 0;
+        }
+
+        public char getCharValue(InternalWorkingMemory workingMemory,
+                                 final Object object) {
+            //  Auto-generated method stub
+            return 0;
+        }
+
+        public double getDoubleValue(InternalWorkingMemory workingMemory,
+                                     final Object object) {
+            //  Auto-generated method stub
+            return 0;
+        }
+
+        public Class getExtractToClass() {
+            //  Auto-generated method stub
+            return null;
+        }
+
+        public String getExtractToClassName() {
+            //  Auto-generated method stub
+            return null;
+        }
+
+        public float getFloatValue(InternalWorkingMemory workingMemory,
+                                   final Object object) {
+            //  Auto-generated method stub
+            return 0;
+        }
+
+        public int getIntValue(InternalWorkingMemory workingMemory,
+                               final Object object) {
+            //  Auto-generated method stub
+            return 0;
+        }
+
+        public long getLongValue(InternalWorkingMemory workingMemory,
+                                 final Object object) {
+            //  Auto-generated method stub
+            return 0;
+        }
+
+        public Method getNativeReadMethod() {
+            //  Auto-generated method stub
+            return null;
+        }
+
+        public short getShortValue(InternalWorkingMemory workingMemory,
+                                   final Object object) {
+            //  Auto-generated method stub
+            return 0;
+        }
+
+        public Object getValue(InternalWorkingMemory workingMemory,
+                               final Object object) {
+            //  Auto-generated method stub
+            return null;
+        }
+
+        public boolean isNullValue(final Object object,
+                                   InternalWorkingMemory workingMemory) {
+            return false;
+        }
+
+        public ValueType getValueType() {
+            //  Auto-generated method stub
+            return ValueType.STRING_TYPE;
+        }
+
+        public int getHashCode(InternalWorkingMemory workingMemory,
+                               final Object object) {
+            return 0;
+        }
+
+        public boolean isGlobal() {
+            // TODO Auto-generated method stub
+            return false;
+        }
+
+        public boolean isNullValue(InternalWorkingMemory workingMemory,
+                                   Object object) {
+            // TODO Auto-generated method stub
+            return false;
+        }
+
+    }
+
+    static class MockBetaNode extends BetaNode {
+
+        MockBetaNode(final int id,
+                     final TupleSource leftInput,
+                     final ObjectSource rightInput) {
+            super( id,
+                   leftInput,
+                   rightInput,
+                   EmptyBetaConstraints.getInstance() );
+            //  Auto-generated constructor stub
+        }
+
+        public void updateSink(final TupleSink sink,
+                               final PropagationContext context,
+                               final InternalWorkingMemory workingMemory) {
+            //  Auto-generated method stub
+
+        }
+
+        public void assertTuple(final ReteTuple tuple,
+                                final PropagationContext context,
+                                final InternalWorkingMemory workingMemory) {
+            //  Auto-generated method stub
+
+        }
+
+        public void retractTuple(final ReteTuple tuple,
+                                 final PropagationContext context,
+                                 final InternalWorkingMemory workingMemory) {
+            //  Auto-generated method stub
+
+        }
+
+        public void assertObject(final InternalFactHandle handle,
+                                 final PropagationContext context,
+                                 final InternalWorkingMemory workingMemory) {
+            //  Auto-generated method stub
+
+        }
+
+        public void retractObject(final InternalFactHandle handle,
+                                  final PropagationContext context,
+                                  final InternalWorkingMemory workingMemory) {
+            //  Auto-generated method stub
+
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/CrossProductTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/CrossProductTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/CrossProductTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,120 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.base.ClassObjectType;
+import org.drools.rule.Pattern;
+import org.drools.rule.Declaration;
+import org.drools.rule.Package;
+import org.drools.rule.Rule;
+import org.drools.spi.Consequence;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.ObjectType;
+
+public class CrossProductTest extends TestCase {
+    private Package       pkg;
+    private WorkingMemory workingMemory;
+    private List          values;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        final ObjectType list1ObjectType = new ClassObjectType( String.class );
+        final ObjectType list2ObjectType = new ClassObjectType( String.class );
+
+        final Rule rule = new Rule( "rule-1" );
+
+        final Pattern list1Pattern = new Pattern( 0,
+                                               list1ObjectType,
+                                               "s1" );
+        final Pattern list2Pattern = new Pattern( 1,
+                                               list2ObjectType,
+                                               "s2" );
+
+        rule.addPattern( list1Pattern );
+        rule.addPattern( list2Pattern );
+
+        final Declaration s1Declaration = rule.getDeclaration( "s1" );
+        final Declaration s2Declaration = rule.getDeclaration( "s2" );
+
+        this.values = new ArrayList();
+
+        rule.setConsequence( new Consequence() {
+
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(final KnowledgeHelper knowledgeHelper,
+                                 final WorkingMemory workingMemory) throws Exception {
+                final String s1 = (String) knowledgeHelper.get( s1Declaration );
+                final String s2 = (String) knowledgeHelper.get( s2Declaration );
+                CrossProductTest.this.values.add( new String[]{s1, s2} );
+            }
+
+        } );
+
+        this.pkg = new Package( "org.drools" );
+        this.pkg.addRule( rule );
+    }
+
+    public void testNotRemoveIdentities() throws Exception {
+        // Default is remove identity FALSE
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+        ruleBase.addPackage( this.pkg );
+
+        this.workingMemory = ruleBase.newStatefulSession();
+        this.workingMemory.insert( "F1" );
+        this.workingMemory.insert( "F2" );
+        this.workingMemory.insert( "F3" );
+        this.workingMemory.insert( "F4" );
+
+        this.workingMemory.fireAllRules();
+
+        // A full cross product is 16, this is just 12
+        assertEquals( 16,
+                      this.values.size() );
+    }
+
+    public void testRemoveIdentities() throws Exception {
+        System.setProperty( "drools.removeIdentities",
+                            "true" );
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+        ruleBase.addPackage( this.pkg );
+
+        this.workingMemory = ruleBase.newStatefulSession();
+        this.workingMemory.insert( "F1" );
+        this.workingMemory.insert( "F2" );
+        this.workingMemory.insert( "F3" );
+        this.workingMemory.insert( "F4" );
+
+        this.workingMemory.fireAllRules();
+
+        // A full cross product is 16, this is just 12
+        assertEquals( 12,
+                      this.values.size() );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/DefaultFactHandleFactoryTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/DefaultFactHandleFactoryTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/DefaultFactHandleFactoryTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,81 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import junit.framework.TestCase;
+
+import org.drools.common.DefaultFactHandle;
+
+public class DefaultFactHandleFactoryTest extends TestCase {
+
+    /*
+     * Class under test for FactHandle newFactHandle()
+     */
+    public void testNewFactHandle() {
+        final ReteooFactHandleFactory factory = new ReteooFactHandleFactory();
+        DefaultFactHandle handle = (DefaultFactHandle) factory.newFactHandle( "cheese", false, null );
+        assertEquals( 0,
+                      handle.getId() );
+        assertEquals( 0,
+                      handle.getRecency() );
+
+        // issue  new handle
+        handle = (DefaultFactHandle) factory.newFactHandle( "cheese", false, null );
+        assertEquals( 1,
+                      handle.getId() );
+        assertEquals( 1,
+                      handle.getRecency() );
+
+        // issue  new handle, under a different reference so we  can destroy later        
+        final DefaultFactHandle handle2 = (DefaultFactHandle) factory.newFactHandle( "cheese", false, null );
+        assertEquals( 2,
+                      handle2.getId() );
+        assertEquals( 2,
+                      handle2.getRecency() );
+
+        // Check recency increasion works
+        factory.increaseFactHandleRecency( handle );
+        assertEquals( 3,
+                      handle.getRecency() );
+
+        // issue new handle and make sure  recency is still inline
+        handle = (DefaultFactHandle) factory.newFactHandle( "cheese", false, null );
+        assertEquals( 3,
+                      handle.getId() );
+        assertEquals( 4,
+                      handle.getRecency() );
+
+        // destroy handle
+        factory.destroyFactHandle( handle2 );
+
+        // issue  new  fact handle and  make sure it  recycled the  id=2
+        handle = (DefaultFactHandle) factory.newFactHandle( "cheese", false, null );
+        assertEquals( 2,
+                      handle.getId() );
+        assertEquals( 5,
+                      handle.getRecency() );
+
+        // issue new  handle  making  sure it correctly resumes  ids  and recency
+        handle = (DefaultFactHandle) factory.newFactHandle( "cheese", false, null );
+        assertEquals( 4,
+                      handle.getId() );
+        assertEquals( 6,
+                      handle.getRecency() );
+
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/EvalConditionNodeTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/EvalConditionNodeTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/EvalConditionNodeTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,306 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.DroolsTestCase;
+import org.drools.FactException;
+import org.drools.RuleBaseFactory;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.PropagationContextImpl;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.spi.PropagationContext;
+import org.drools.util.TupleHashTable;
+
+public class EvalConditionNodeTest extends DroolsTestCase {
+    private PropagationContext  context;
+    private ReteooWorkingMemory workingMemory;
+    private ReteooRuleBase ruleBase;
+    private BuildContext buildContext;    
+
+    public EvalConditionNodeTest(final String name) {
+        super( name );
+    }
+
+    public void setUp() {
+        this.ruleBase = ( ReteooRuleBase ) RuleBaseFactory.newRuleBase();
+        this.buildContext = new BuildContext( ruleBase, ((ReteooRuleBase)ruleBase).getReteooBuilder().getIdGenerator() );
+        
+        this.context = new PropagationContextImpl( 0,
+                                                   PropagationContext.ASSERTION,
+                                                   null,
+                                                   null );
+
+        this.workingMemory = ( ReteooWorkingMemory ) this.ruleBase.newStatefulSession();
+    }
+
+    public void testAttach() throws Exception {
+        final MockTupleSource source = new MockTupleSource( 12 );
+
+        final EvalConditionNode node = new EvalConditionNode( 18,
+                                                              source,
+                                                              new MockEvalCondition( true ),
+                                                              buildContext );
+
+        assertEquals( 18,
+                      node.getId() );
+
+        assertEquals( 0,
+                      source.getAttached() );
+
+        node.attach();
+
+        assertEquals( 1,
+                      source.getAttached() );
+
+    }
+
+    public void testMemory() {
+        final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
+                                                                           (ReteooRuleBase) RuleBaseFactory.newRuleBase() );
+
+        final MockTupleSource source = new MockTupleSource( 12 );
+
+        final EvalConditionNode node = new EvalConditionNode( 18,
+                                                              source,
+                                                              new MockEvalCondition( true ),
+                                                              buildContext );
+
+        final TupleHashTable memory = (TupleHashTable) workingMemory.getNodeMemory( node );
+
+        assertNotNull( memory );
+    }
+
+    /**
+     * If a eval allows an incoming Object, then the Object MUST be
+     * propagated. This tests that the memory is updated
+     * 
+     * @throws FactException
+     */
+    public void testAssertedAllowed() throws FactException {
+        final MockEvalCondition eval = new MockEvalCondition( true );
+
+        // Create a test node that always returns false 
+        final EvalConditionNode node = new EvalConditionNode( 1,
+                                                              new MockTupleSource( 15 ),
+                                                              eval,
+                                                              buildContext );
+
+        final MockTupleSink sink = new MockTupleSink();
+        node.addTupleSink( sink );
+
+        // Create the Tuple
+        final DefaultFactHandle f0 = new DefaultFactHandle( 0,
+                                                            "stilton" );
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        // Tuple should pass and propagate 
+        node.assertTuple( tuple0,
+                          this.context,
+                          this.workingMemory );
+
+        // Create the Tuple
+        final DefaultFactHandle f1 = new DefaultFactHandle( 1,
+                                                            "cheddar" );
+        final ReteTuple tuple1 = new ReteTuple( f1 );
+
+        // Tuple should pass and propagate 
+        node.assertTuple( tuple1,
+                          this.context,
+                          this.workingMemory );
+
+        // Check memory was populated
+        final TupleHashTable memory = (TupleHashTable) this.workingMemory.getNodeMemory( node );
+
+        assertEquals( 2,
+                      memory.size() );
+
+        assertTrue( memory.contains( tuple0 ) );
+        assertTrue( memory.contains( tuple1 ) );
+
+        // make sure assertions were propagated
+        assertEquals( 2,
+                      sink.getAsserted().size() );
+    }
+
+    public void testAssertedAllowedThenRetract() throws FactException {
+        final MockEvalCondition eval = new MockEvalCondition( true );
+
+        // Create a test node that always returns false 
+        final EvalConditionNode node = new EvalConditionNode( 1,
+                                                              new MockTupleSource( 15 ),
+                                                              eval,
+                                                              buildContext );
+
+        final MockTupleSink sink = new MockTupleSink();
+        node.addTupleSink( sink );
+
+        // Create the Tuple
+        final DefaultFactHandle f0 = new DefaultFactHandle( 0,
+                                                            "stilton" );
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        // Tuple should pass and propagate 
+        node.assertTuple( tuple0,
+                          this.context,
+                          this.workingMemory );
+
+        // we create and retract two tuples, checking the linkedtuples is null for JBRULES-246 "NPE on retract()"        
+        // Create the Tuple
+        final DefaultFactHandle f1 = new DefaultFactHandle( 1,
+                                                            "cheddar" );
+        final ReteTuple tuple1 = new ReteTuple( f1 );
+
+        // Tuple should pass and propagate 
+        node.assertTuple( tuple1,
+                          this.context,
+                          this.workingMemory );
+
+        // Check memory was populated
+        final TupleHashTable memory = (TupleHashTable) this.workingMemory.getNodeMemory( node );
+
+        assertEquals( 2,
+                      memory.size() );
+        assertTrue( memory.contains( tuple0 ) );
+        assertTrue( memory.contains( tuple1 ) );
+
+        // make sure assertions were propagated
+        assertEquals( 2,
+                      sink.getAsserted().size() );
+
+        // Now test that the fact is retracted correctly
+        node.retractTuple( tuple0,
+                           this.context,
+                           this.workingMemory );
+
+        // Now test that the fact is retracted correctly
+        assertEquals( 1,
+                      memory.size() );
+
+        assertTrue( memory.contains( tuple1 ) );
+
+        // make sure retractions were propagated
+        assertEquals( 1,
+                      sink.getRetracted().size() );
+
+        // Now test that the fact is retracted correctly
+        node.retractTuple( tuple1,
+                           this.context,
+                           this.workingMemory );
+
+        // Now test that the fact is retracted correctly
+        assertEquals( 0,
+                      memory.size() );
+
+        // make sure retractions were propagated
+        assertEquals( 2,
+                      sink.getRetracted().size() );
+    }
+
+    public void testAssertedNotAllowed() throws FactException {
+        final MockEvalCondition eval = new MockEvalCondition( false );
+
+        // Create a test node that always returns false 
+        final EvalConditionNode node = new EvalConditionNode( 1,
+                                                              new MockTupleSource( 15 ),
+                                                              eval,
+                                                              buildContext );
+
+        final MockTupleSink sink = new MockTupleSink();
+        node.addTupleSink( sink );
+
+        // Create the Tuple
+        final DefaultFactHandle f0 = new DefaultFactHandle( 0,
+                                                            "stilton" );
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        // Tuple should fail and not propagate
+        node.assertTuple( tuple0,
+                          this.context,
+                          this.workingMemory );
+
+        // Create the Tuple
+        final DefaultFactHandle f1 = new DefaultFactHandle( 1,
+                                                            "cheddar" );
+        final ReteTuple tuple1 = new ReteTuple( f1 );
+
+        // Tuple should fail and not propagate 
+        node.assertTuple( tuple1,
+                          this.context,
+                          this.workingMemory );
+
+        // Check memory was not populated
+        final TupleHashTable memory = (TupleHashTable) this.workingMemory.getNodeMemory( node );
+
+        assertEquals( 0,
+                      memory.size() );
+
+        // test no propagations
+        assertEquals( 0,
+                      sink.getAsserted().size() );
+        assertEquals( 0,
+                      sink.getRetracted().size() );
+    }
+
+    public void testUpdateWithMemory() throws FactException {
+        // If no child nodes have children then we need to re-process the left
+        // and right memories
+        // as a joinnode does not store the resulting tuples
+        final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
+                                                                           (ReteooRuleBase) RuleBaseFactory.newRuleBase() );
+
+        // Creat the object source so we can detect the alphaNode telling it to
+        // propate its contents
+        //final MockTupleSource source = new MockTupleSource( 1 );
+
+        /* Create a test node that always returns true */
+        final EvalConditionNode node = new EvalConditionNode( 1,
+                                                              new MockTupleSource( 15 ),
+                                                              new MockEvalCondition( true ),
+                                                              buildContext );
+
+        // Add the first tuple sink and assert a tuple and object
+        // The sink has no memory
+        final MockTupleSink sink1 = new MockTupleSink( 2 );
+        node.addTupleSink( sink1 );
+
+        final DefaultFactHandle f0 = new DefaultFactHandle( 0,
+                                                            "string0" );
+
+        final ReteTuple tuple1 = new ReteTuple( f0 );
+
+        node.assertTuple( tuple1,
+                          this.context,
+                          workingMemory );
+
+        assertLength( 1,
+                      sink1.getAsserted() );
+
+        // Add the new sink, this should be updated from the re-processed
+        // joinnode memory
+        final MockTupleSink sink2 = new MockTupleSink( 3 );
+        node.addTupleSink( sink2 );
+        assertLength( 0,
+                      sink2.getAsserted() );
+
+        node.updateSink( sink2,
+                         this.context,
+                         workingMemory );
+
+        assertLength( 1,
+                      sink2.getAsserted() );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ExistsNodeTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ExistsNodeTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ExistsNodeTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,294 @@
+/*
+ * Copyright 2006 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;
+
+import java.beans.IntrospectionException;
+
+import junit.framework.Assert;
+
+import org.drools.Cheese;
+import org.drools.DroolsTestCase;
+import org.drools.FactException;
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuleBaseFactory;
+import org.drools.common.DefaultBetaConstraints;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.PropagationContextImpl;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.Rule;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.spi.MockConstraint;
+import org.drools.spi.PropagationContext;
+
+/**
+ * @author etirelli
+ *
+ */
+public class ExistsNodeTest extends DroolsTestCase {
+    Rule                  rule;
+    PropagationContext    context;
+    ReteooWorkingMemory   workingMemory;
+    MockObjectSource      objectSource;
+    MockTupleSource       tupleSource;
+    MockTupleSink         sink;
+    ExistsNode            node;
+    RightInputAdapterNode ria;
+    BetaMemory            memory;
+    MockConstraint        constraint = new MockConstraint();
+
+    /**
+     * Setup the BetaNode used in each of the tests
+     * @throws IntrospectionException 
+     */
+    public void setUp() throws IntrospectionException {
+        this.rule = new Rule( "test-rule" );
+        this.context = new PropagationContextImpl( 0,
+                                                   PropagationContext.ASSERTION,
+                                                   null,
+                                                   null );
+
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ruleBase.getReteooBuilder().getIdGenerator() );
+
+        this.workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final RuleBaseConfiguration configuration = new RuleBaseConfiguration();
+
+        // string1Declaration is bound to pattern 3 
+        this.node = new ExistsNode( 15,
+                                    new MockTupleSource( 5 ),
+                                    new MockObjectSource( 8 ),
+                                    new DefaultBetaConstraints( new BetaNodeFieldConstraint[]{this.constraint},
+                                                                configuration ),
+                                    buildContext );
+
+        this.sink = new MockTupleSink();
+        this.node.addTupleSink( this.sink );
+
+        this.memory = (BetaMemory) this.workingMemory.getNodeMemory( this.node );
+    }
+
+    /**
+     * Test assertion with both Objects and Tuples
+     * 
+     * @throws AssertionException
+     */
+    public void testExistsStandard() throws FactException {
+        // assert tuple
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           10 );
+        final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.insert( cheddar );
+
+        final ReteTuple tuple1 = new ReteTuple( f0 );
+
+        this.node.assertTuple( tuple1,
+                               this.context,
+                               this.workingMemory );
+
+        // no matching objects, so should not propagate
+        assertLength( 0,
+                      this.sink.getAsserted() );
+
+        assertLength( 0,
+                      this.sink.getRetracted() );
+
+        // assert will match, so should propagate
+        final Cheese brie = new Cheese( "brie",
+                                        10 );
+        final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.insert( brie );
+
+        this.node.assertObject( f1,
+                                this.context,
+                                this.workingMemory );
+
+        // check a single assertion
+        assertLength( 1,
+                      this.sink.getAsserted() );
+
+        assertLength( 0,
+                      this.sink.getRetracted() );
+
+        assertEquals( new ReteTuple( f0 ),
+                      ((Object[]) this.sink.getAsserted().get( 0 ))[0] );
+
+        // assert tuple, will have matches, so propagate
+        final DefaultFactHandle f2 = (DefaultFactHandle) this.workingMemory.insert( new Cheese( "gouda",
+                                                                                                10 ) );
+        final ReteTuple tuple2 = new ReteTuple( f2 );
+        this.node.assertTuple( tuple2,
+                               this.context,
+                               this.workingMemory );
+
+        // check propagations 
+        assertLength( 2,
+                      this.sink.getAsserted() );
+
+        assertLength( 0,
+                      this.sink.getRetracted() );
+
+        // check memory sizes
+        assertEquals( 2,
+                      this.memory.getTupleMemory().size() );
+        assertEquals( 1,
+                      this.memory.getFactHandleMemory().size() );
+
+        // When this is retracter both tuples should be retracted
+        this.node.retractObject( f1,
+                                 this.context,
+                                 this.workingMemory );
+
+        // check retracts 
+        assertLength( 2,
+                      this.sink.getAsserted() );
+
+        assertLength( 2,
+                      this.sink.getRetracted() );
+    }
+
+    /**
+     * Test assertion with both Objects and Tuples
+     * 
+     * @throws AssertionException
+     */
+    public void testExistsWithConstraints() throws FactException {
+        this.constraint.isAllowed = false;
+
+        // assert tuple
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           10 );
+        final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.insert( cheddar );
+
+        final ReteTuple tuple1 = new ReteTuple( f0 );
+
+        this.node.assertTuple( tuple1,
+                               this.context,
+                               this.workingMemory );
+
+        // no matching objects, so don't propagate
+        assertLength( 0,
+                      this.sink.getAsserted() );
+
+        assertLength( 0,
+                      this.sink.getRetracted() );
+
+        // assert will not match, so activation should stay propagated
+        final Cheese brie = new Cheese( "brie",
+                                        10 );
+        final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.insert( brie );
+
+        this.node.assertObject( f1,
+                                this.context,
+                                this.workingMemory );
+
+        // no matches, so no propagations still
+        assertLength( 0,
+                      this.sink.getAsserted() );
+
+        assertLength( 0,
+                      this.sink.getRetracted() );
+
+        // assert tuple, will have matches, so do assert propagation
+        final DefaultFactHandle f2 = (DefaultFactHandle) this.workingMemory.insert( new Cheese( "gouda",
+                                                                                                10 ) );
+        final ReteTuple tuple2 = new ReteTuple( f2 );
+        this.node.assertTuple( tuple2,
+                               this.context,
+                               this.workingMemory );
+
+        assertLength( 0,
+                      this.sink.getAsserted() );
+
+        assertLength( 0,
+                      this.sink.getRetracted() );
+    }
+
+    /**
+     * Tests memory consistency after insert/update/retract calls
+     * 
+     * @throws AssertionException
+     */
+    public void testExistsMemoryManagement() throws FactException {
+        try {
+            // assert tuple
+            final Cheese cheddar = new Cheese( "cheddar",
+                                               10 );
+            final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.insert( cheddar );
+            final ReteTuple tuple1 = new ReteTuple( f0 );
+
+            this.node.assertTuple( tuple1,
+                                   this.context,
+                                   this.workingMemory );
+
+            // assert will match, so should propagate
+            final Cheese brie = new Cheese( "brie",
+                                            10 );
+            final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.insert( brie );
+
+            // Initially, no objects in right memory
+            assertEquals( 0,
+                          this.memory.getFactHandleMemory().size() );
+            this.node.assertObject( f1,
+                                    this.context,
+                                    this.workingMemory );
+
+            // Now, needs to have 1 object in right memory
+            assertEquals( 1,
+                          this.memory.getFactHandleMemory().size() );
+
+            // simulate modify
+            this.node.retractObject( f1,
+                                     this.context,
+                                     this.workingMemory );
+            this.node.assertObject( f1,
+                                    this.context,
+                                    this.workingMemory );
+            // Memory should not change
+            assertEquals( 1,
+                          this.memory.getFactHandleMemory().size() );
+
+            // When this is retracter both tuples should assert
+            this.node.retractObject( f1,
+                                     this.context,
+                                     this.workingMemory );
+            assertEquals( 0,
+                          this.memory.getFactHandleMemory().size() );
+
+            // check memory sizes
+            assertEquals( 1,
+                          this.memory.getTupleMemory().size() );
+
+            // simulate modify
+            this.node.retractTuple( tuple1,
+                                    this.context,
+                                    this.workingMemory );
+            this.node.assertTuple( tuple1,
+                                   this.context,
+                                   this.workingMemory );
+            assertEquals( 1,
+                          this.memory.getTupleMemory().size() );
+            this.node.retractTuple( tuple1,
+                                    this.context,
+                                    this.workingMemory );
+            assertEquals( 0,
+                          this.memory.getTupleMemory().size() );
+        } catch ( final Exception e ) {
+            Assert.fail( "No exception should be raised in this procedure, but got: " + e.toString() );
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/FactHandleTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/FactHandleTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/FactHandleTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,89 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import junit.framework.TestCase;
+
+import org.drools.common.DefaultFactHandle;
+
+public class FactHandleTest extends TestCase {
+    /*
+     * Class under test for void FactHandleImpl(long)
+     */
+    public void testFactHandleImpllong() {
+        final DefaultFactHandle f0 = new DefaultFactHandle( 134,
+                                                            "cheese" );
+        assertEquals( 134,
+                      f0.getId() );
+        assertEquals( 134,
+                      f0.getRecency() );
+    }
+
+    /*
+     * Class under test for void FactHandleImpl(long, long)
+     */
+    public void testFactHandleImpllonglong() {
+        final DefaultFactHandle f0 = new DefaultFactHandle( 134,
+                                                            "cheese",
+                                                            678 );
+        assertEquals( 134,
+                      f0.getId() );
+        assertEquals( 678,
+                      f0.getRecency() );
+    }
+
+    /*
+     * Class under test for boolean equals(Object)
+     */
+    public void testEqualsObject() {
+        final DefaultFactHandle f0 = new DefaultFactHandle( 134,
+                                                            "cheese" );
+        final DefaultFactHandle f1 = new DefaultFactHandle( 96,
+                                                            "cheese" );
+        final DefaultFactHandle f3 = new DefaultFactHandle( 96,
+                                                            "cheese" );
+
+        assertFalse( "f0 should not equal f1",
+                     f0.equals( f1 ) );
+        assertEquals( f1,
+                      f3 );
+        assertNotSame( f1,
+                       f3 );
+    }
+
+    public void testHashCode() {
+        final DefaultFactHandle f0 = new DefaultFactHandle( 234,
+                                                            "cheese" );
+        assertEquals( "cheese".hashCode(),
+                      f0.getObjectHashCode() );
+
+        assertEquals( 234,
+                      f0.hashCode() );
+    }
+
+    public void testInvalidate() {
+        final DefaultFactHandle f0 = new DefaultFactHandle( 134,
+                                                            "cheese" );
+        assertEquals( 134,
+                      f0.getId() );
+
+        f0.invalidate();
+        assertEquals( -1,
+                      f0.getId() );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/FromNodeTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/FromNodeTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/FromNodeTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,348 @@
+package org.drools.reteoo;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.drools.Cheese;
+import org.drools.FactHandle;
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.base.ClassFieldExtractor;
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.ClassObjectType;
+import org.drools.base.FieldFactory;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.EqualityEvaluatorsDefinition;
+import org.drools.base.evaluators.Operator;
+import org.drools.common.BetaConstraints;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.PropagationContextImpl;
+import org.drools.common.SingleBetaConstraints;
+import org.drools.rule.Declaration;
+import org.drools.rule.LiteralConstraint;
+import org.drools.rule.Pattern;
+import org.drools.rule.VariableConstraint;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.DataProvider;
+import org.drools.spi.FieldValue;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
+import org.drools.util.LinkedList;
+import org.drools.util.LinkedListEntry;
+
+public class FromNodeTest extends TestCase {
+    ClassFieldExtractorCache cache = ClassFieldExtractorCache.getInstance();
+    EqualityEvaluatorsDefinition equals = new EqualityEvaluatorsDefinition();
+
+    public void testAlphaNode() {
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+        final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
+                                                                           (ReteooRuleBase) RuleBaseFactory.newRuleBase() );
+        final ClassFieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                                  "type",
+                                                                  getClass().getClassLoader() );
+
+        final FieldValue field = FieldFactory.getFieldValue( "stilton" );
+        final LiteralConstraint constraint = new LiteralConstraint( extractor,
+                                                                    equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ),
+                                                                    field );
+
+        final List list = new ArrayList();
+        final Cheese cheese1 = new Cheese( "cheddar",
+                                           20 );
+        final Cheese cheese2 = new Cheese( "brie",
+                                           20 );
+        list.add( cheese1 );
+        list.add( cheese2 );
+        final MockDataProvider dataProvider = new MockDataProvider( list );
+
+        final FromNode from = new FromNode( 3,
+                                            dataProvider,
+                                            null,
+                                            new AlphaNodeFieldConstraint[]{constraint},
+                                            null );
+        final MockTupleSink sink = new MockTupleSink( 5 );
+        from.addTupleSink( sink );
+
+        final Person person1 = new Person( "xxx1",
+                                           30 );
+        final FactHandle person1Handle = workingMemory.insert( person1 );
+        final ReteTuple tuple1 = new ReteTuple( (DefaultFactHandle) person1Handle );
+        from.assertTuple( tuple1,
+                          context,
+                          workingMemory );
+
+        // nothing should be asserted, as cheese1 is cheddar and we are filtering on stilton
+        assertEquals( 0,
+                      sink.getAsserted().size() );
+
+        //Set cheese1 to stilton and it should now propagate
+        cheese1.setType( "stilton" );
+        final Person person2 = new Person( "xxx2",
+                                           30 );
+        final FactHandle person2Handle = workingMemory.insert( person2 );
+        final ReteTuple tuple2 = new ReteTuple( (DefaultFactHandle) person2Handle );
+        from.assertTuple( tuple2,
+                          context,
+                          workingMemory );
+
+        final List asserted = sink.getAsserted();
+        assertEquals( 1,
+                      asserted.size() );
+        Tuple tuple = (Tuple) ((Object[]) asserted.get( 0 ))[0];
+        assertSame( person2,
+                    tuple.getFactHandles()[1].getObject() );
+        assertSame( cheese1,
+                    tuple.getFactHandles()[0].getObject() );
+
+        cheese2.setType( "stilton" );
+        final Person person3 = new Person( "xxx2",
+                                           30 );
+        final FactHandle person3Handle = workingMemory.insert( person3 );
+        final ReteTuple tuple3 = new ReteTuple( (DefaultFactHandle) person3Handle );
+        from.assertTuple( tuple3,
+                          context,
+                          workingMemory );
+
+        assertEquals( 3,
+                      asserted.size() );
+        tuple = (Tuple) ((Object[]) asserted.get( 1 ))[0];
+        assertSame( person3,
+                    tuple.getFactHandles()[1].getObject() );
+        assertSame( cheese1,
+                    tuple.getFactHandles()[0].getObject() );
+        tuple = (Tuple) ((Object[]) asserted.get( 2 ))[0];
+        assertSame( person3,
+                    tuple.getFactHandles()[1].getObject() );
+        assertSame( cheese2,
+                    tuple.getFactHandles()[0].getObject() );
+
+        assertNotSame( cheese1,
+                       cheese2 );
+    }
+
+    public void testBetaNode() {
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+
+        final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
+                                                                           (ReteooRuleBase) RuleBaseFactory.newRuleBase() );
+
+        final ClassFieldExtractor priceExtractor = cache.getExtractor( Cheese.class,
+                                                                       "price",
+                                                                       getClass().getClassLoader() );
+
+        final ClassFieldExtractor ageExtractor = cache.getExtractor( Person.class,
+                                                                     "age",
+                                                                     getClass().getClassLoader() );
+
+        final Pattern pattern = new Pattern( 0,
+                                             new ClassObjectType( Person.class ) );
+
+        final Declaration declaration = new Declaration( "age",
+                                                         ageExtractor,
+                                                         pattern );
+
+        final VariableConstraint variableConstraint = new VariableConstraint( priceExtractor,
+                                                                              declaration,
+                                                                              equals.getEvaluator( ValueType.PINTEGER_TYPE, Operator.EQUAL ) );
+        final RuleBaseConfiguration configuration = new RuleBaseConfiguration();
+        configuration.setIndexRightBetaMemory( false );
+        configuration.setIndexLeftBetaMemory( false );
+        final BetaConstraints betaConstraints = new SingleBetaConstraints( variableConstraint,
+                                                                           configuration );
+
+        final List list = new ArrayList();
+        final Cheese cheese1 = new Cheese( "cheddar",
+                                           18 );
+        final Cheese cheese2 = new Cheese( "brie",
+                                           12 );
+        list.add( cheese1 );
+        list.add( cheese2 );
+        final MockDataProvider dataProvider = new MockDataProvider( list );
+
+        final FromNode from = new FromNode( 3,
+                                            dataProvider,
+                                            null,
+                                            null,
+                                            betaConstraints );
+        final MockTupleSink sink = new MockTupleSink( 5 );
+        from.addTupleSink( sink );
+
+        final Person person1 = new Person( "xxx1",
+                                           30 );
+        final FactHandle person1Handle = workingMemory.insert( person1 );
+        final ReteTuple tuple1 = new ReteTuple( (DefaultFactHandle) person1Handle );
+        from.assertTuple( tuple1,
+                          context,
+                          workingMemory );
+
+        // nothing should be asserted, as cheese1 is cheddar and we are filtering on stilton
+        assertEquals( 0,
+                      sink.getAsserted().size() );
+
+        //Set cheese1 to stilton and it should now propagate
+        cheese1.setPrice( 30 );
+        final Person person2 = new Person( "xxx2",
+                                           30 );
+        final FactHandle person2Handle = workingMemory.insert( person2 );
+        final ReteTuple tuple2 = new ReteTuple( (DefaultFactHandle) person2Handle );
+        from.assertTuple( tuple2,
+                          context,
+                          workingMemory );
+
+        final List asserted = sink.getAsserted();
+        assertEquals( 1,
+                      asserted.size() );
+        Tuple tuple = (Tuple) ((Object[]) asserted.get( 0 ))[0];
+        assertSame( person2,
+                    tuple.getFactHandles()[1].getObject() );
+        assertSame( cheese1,
+                    tuple.getFactHandles()[0].getObject() );
+
+        cheese2.setPrice( 30 );
+        final Person person3 = new Person( "xxx2",
+                                           30 );
+        final FactHandle person3Handle = workingMemory.insert( person3 );
+        final ReteTuple tuple3 = new ReteTuple( (DefaultFactHandle) person3Handle );
+        from.assertTuple( tuple3,
+                          context,
+                          workingMemory );
+
+        assertEquals( 3,
+                      asserted.size() );
+        tuple = (Tuple) ((Object[]) asserted.get( 1 ))[0];
+        assertSame( person3,
+                    tuple.getFactHandles()[1].getObject() );
+        assertSame( cheese1,
+                    tuple.getFactHandles()[0].getObject() );
+        tuple = (Tuple) ((Object[]) asserted.get( 2 ))[0];
+        assertSame( person3,
+                    tuple.getFactHandles()[1].getObject() );
+        assertSame( cheese2,
+                    tuple.getFactHandles()[0].getObject() );
+
+        assertNotSame( cheese1,
+                       cheese2 );
+    }
+
+    public void testRestract() {
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+        final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
+                                                                           (ReteooRuleBase) RuleBaseFactory.newRuleBase() );
+        final ClassFieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                                  "type",
+                                                                  getClass().getClassLoader() );
+
+        final FieldValue field = FieldFactory.getFieldValue( "stilton" );
+        final LiteralConstraint constraint = new LiteralConstraint( extractor,
+                                                                    equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ),
+                                                                    field );
+
+        final List list = new ArrayList();
+        final Cheese cheese1 = new Cheese( "stilton",
+                                           5 );
+        final Cheese cheese2 = new Cheese( "stilton",
+                                           15 );
+        list.add( cheese1 );
+        list.add( cheese2 );
+        final MockDataProvider dataProvider = new MockDataProvider( list );
+
+        final FromNode from = new FromNode( 3,
+                                            dataProvider,
+                                            null,
+                                            new AlphaNodeFieldConstraint[]{constraint},
+                                            null );
+        final MockTupleSink sink = new MockTupleSink( 5 );
+        from.addTupleSink( sink );
+
+        final List asserted = sink.getAsserted();
+
+        final Person person1 = new Person( "xxx2",
+                                           30 );
+        final FactHandle person1Handle = workingMemory.insert( person1 );
+        final ReteTuple tuple = new ReteTuple( (DefaultFactHandle) person1Handle );
+        from.assertTuple( tuple,
+                          context,
+                          workingMemory );
+
+        assertEquals( 2,
+                      asserted.size() );
+
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( from );
+        assertEquals( 1,
+                      memory.getTupleMemory().size() );
+        assertNull( memory.getFactHandleMemory() );
+        assertEquals( 2,
+                      ((LinkedList) memory.getCreatedHandles().get( tuple )).size() );
+
+        final InternalFactHandle handle1 = (InternalFactHandle) ((LinkedListEntry) ((LinkedList) memory.getCreatedHandles().get( tuple )).getFirst()).getObject();
+        final InternalFactHandle handle2 = (InternalFactHandle) ((LinkedListEntry) ((LinkedList) memory.getCreatedHandles().get( tuple )).getLast()).getObject();
+        assertEquals( handle1.getObject(),
+                      cheese1 );
+        assertEquals( handle2.getObject(),
+                      cheese2 );
+
+        from.retractTuple( tuple,
+                           context,
+                           workingMemory );
+        assertEquals( 0,
+                      memory.getTupleMemory().size() );
+        assertNull( memory.getFactHandleMemory() );
+    }
+
+    public static class MockDataProvider
+        implements
+        DataProvider {
+
+        private Collection collection;
+
+        public Declaration[] getRequiredDeclarations() {
+            return null;
+        }
+
+        public MockDataProvider(final Collection collection) {
+            this.collection = collection;
+        }
+
+        public Iterator getResults(final Tuple tuple,
+                                   final WorkingMemory wm,
+                                   final PropagationContext ctx) {
+            return this.collection.iterator();
+        }
+    }
+
+    public static class Person {
+        private String name;
+        private int    age;
+
+        public Person(final String name,
+                      final int age) {
+            super();
+            this.name = name;
+            this.age = age;
+        }
+
+        public int getAge() {
+            return this.age;
+        }
+
+        public String getName() {
+            return this.name;
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/InstrumentedReteTuple.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/InstrumentedReteTuple.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/InstrumentedReteTuple.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,38 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.FactHandle;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
+
+public class InstrumentedReteTuple extends ReteTuple {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    public InstrumentedReteTuple(final ReteTuple left,
+                                 final FactHandle handle) {
+        super( left,
+               (InternalFactHandle) handle );
+    }
+
+    public InstrumentedReteTuple(final FactHandle handle) {
+        super( (DefaultFactHandle) handle );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/JoinNodeTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/JoinNodeTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/JoinNodeTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,486 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.DroolsTestCase;
+import org.drools.RuleBase;
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuleBaseFactory;
+import org.drools.common.DefaultBetaConstraints;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.EmptyBetaConstraints;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.PropagationContextImpl;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.Rule;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.spi.MockConstraint;
+import org.drools.spi.PropagationContext;
+import org.drools.util.FactEntry;
+import org.drools.util.Iterator;
+
+public class JoinNodeTest extends DroolsTestCase {
+    Rule                rule;
+    PropagationContext  context;
+    ReteooWorkingMemory workingMemory;
+    MockObjectSource    objectSource;
+    MockTupleSource     tupleSource;
+    MockTupleSink       sink;
+    BetaNode            node;
+    BetaMemory          memory;
+    MockConstraint      constraint = new MockConstraint();
+
+    /**
+     * Setup the BetaNode used in each of the tests
+     */
+    public void setUp() {
+        this.rule = new Rule( "test-rule" );
+        this.context = new PropagationContextImpl( 0,
+                                                   PropagationContext.ASSERTION,
+                                                   null,
+                                                   null );
+        this.workingMemory = new ReteooWorkingMemory( 1,
+                                                      (ReteooRuleBase) RuleBaseFactory.newRuleBase() );
+
+        this.tupleSource = new MockTupleSource( 4 );
+        this.objectSource = new MockObjectSource( 4 );
+        this.sink = new MockTupleSink();
+
+        final RuleBaseConfiguration configuration = new RuleBaseConfiguration();
+        
+        ReteooRuleBase ruleBase = ( ReteooRuleBase ) RuleBaseFactory.newRuleBase();
+        BuildContext buildContext = new BuildContext( ruleBase, ruleBase.getReteooBuilder().getIdGenerator() );
+
+        this.node = new JoinNode( 15,
+                                  this.tupleSource,
+                                  this.objectSource,
+                                  new DefaultBetaConstraints( new BetaNodeFieldConstraint[]{this.constraint},
+                                                              configuration ),
+                                  buildContext );
+
+        this.node.addTupleSink( this.sink );
+
+        this.memory = (BetaMemory) this.workingMemory.getNodeMemory( this.node );
+
+        // check memories are empty
+        assertEquals( 0,
+                      this.memory.getTupleMemory().size() );
+        assertEquals( 0,
+                      this.memory.getFactHandleMemory().size() );
+
+    }
+
+    public void testAttach() throws Exception {
+        final Field objectFfield = ObjectSource.class.getDeclaredField( "sink" );
+        objectFfield.setAccessible( true );
+        ObjectSinkPropagator objectSink = (ObjectSinkPropagator) objectFfield.get( this.objectSource );
+
+        final Field tupleField = TupleSource.class.getDeclaredField( "sink" );
+        tupleField.setAccessible( true );
+        TupleSinkPropagator tupleSink = (TupleSinkPropagator) tupleField.get( this.tupleSource );
+
+        assertEquals( 15,
+                      this.node.getId() );
+
+        assertNotNull( objectSink );
+        assertNotNull( tupleSink );
+
+        this.node.attach();
+
+        objectSink = (ObjectSinkPropagator) objectFfield.get( this.objectSource );
+        tupleSink = (TupleSinkPropagator) tupleField.get( this.tupleSource );
+
+        assertEquals( 1,
+                      objectSink.getSinks().length );
+
+        assertEquals( 1,
+                      tupleSink.getSinks().length );
+
+        assertSame( this.node,
+                    objectSink.getSinks()[0] );
+
+        assertSame( this.node,
+                    tupleSink.getSinks()[0] );
+    }
+
+    public void testMemory() {
+        final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
+                                                                           (ReteooRuleBase) RuleBaseFactory.newRuleBase() );
+
+        final MockObjectSource objectSource = new MockObjectSource( 1 );
+        final MockTupleSource tupleSource = new MockTupleSource( 1 );
+
+        ReteooRuleBase ruleBase = ( ReteooRuleBase ) RuleBaseFactory.newRuleBase();
+        BuildContext buildContext = new BuildContext( ruleBase, ruleBase.getReteooBuilder().getIdGenerator() );        
+        final JoinNode joinNode = new JoinNode( 2,
+                                                tupleSource,
+                                                objectSource,
+                                                EmptyBetaConstraints.getInstance(),
+                                                buildContext );
+
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( joinNode );
+
+        assertNotNull( memory );
+    }
+
+    /**
+     * Test just tuple assertions
+     * 
+     * @throws AssertionException
+     */
+    public void testAssertTuple() throws Exception {
+        final DefaultFactHandle f0 = new DefaultFactHandle( 0,
+                                                            "cheese" );
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        // assert tuple, should add one to left memory
+        this.node.assertTuple( tuple0,
+                               this.context,
+                               this.workingMemory );
+        // check memories, left memory is populated, right memory is emptys
+        assertEquals( 1,
+                      this.memory.getTupleMemory().size() );
+        assertEquals( 0,
+                      this.memory.getFactHandleMemory().size() );
+
+        // assert tuple, should add left memory should be 2
+        final DefaultFactHandle f1 = new DefaultFactHandle( 1,
+                                                            "cheese" );
+        final ReteTuple tuple1 = new ReteTuple( f1 );
+        this.node.assertTuple( tuple1,
+                               this.context,
+                               this.workingMemory );
+        assertEquals( 2,
+                      this.memory.getTupleMemory().size() );
+
+        final Iterator it = this.memory.getTupleMemory().iterator();
+        assertEquals( tuple0,
+                      it.next() );
+        assertEquals( tuple1,
+                      it.next() );
+    }
+
+    /**
+     * Test just tuple assertions
+     * 
+     * @throws AssertionException
+     */
+    public void testAssertTupleSequentialMode() throws Exception {
+        RuleBaseConfiguration conf = new RuleBaseConfiguration();
+        conf.setSequential( true );
+
+        this.workingMemory = new ReteooWorkingMemory( 1,
+                                                      (ReteooRuleBase) RuleBaseFactory.newRuleBase( conf ) );
+
+        ReteooRuleBase ruleBase = ( ReteooRuleBase ) RuleBaseFactory.newRuleBase();
+        BuildContext buildContext = new BuildContext( ruleBase, ruleBase.getReteooBuilder().getIdGenerator() );
+        buildContext.setTupleMemoryEnabled( false );
+        buildContext.setObjectTypeNodeMemoryEnabled( false );
+        
+        // override setup, so its working in sequential mode
+        this.node = new JoinNode( 15,
+                                  this.tupleSource,
+                                  this.objectSource,
+                                  new DefaultBetaConstraints( new BetaNodeFieldConstraint[]{this.constraint},
+                                                              conf ),
+                                  buildContext);
+
+        this.node.addTupleSink( this.sink );
+
+        this.memory = (BetaMemory) this.workingMemory.getNodeMemory( this.node );
+
+        final DefaultFactHandle f0 = new DefaultFactHandle( 0,
+                                                            "cheese" );
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        this.node.assertObject( f0,
+                                this.context,
+                                this.workingMemory );
+
+        // assert tuple
+        this.node.assertTuple( tuple0,
+                               this.context,
+                               this.workingMemory );
+
+        assertEquals( 1,
+                      this.sink.getAsserted().size() );
+
+        assertNull( this.memory.getTupleMemory() );
+
+        assertEquals( 1,
+                      this.memory.getFactHandleMemory().size() );
+
+        assertEquals( new ReteTuple( tuple0,
+                                     f0 ),
+                      ((Object[]) this.sink.getAsserted().get( 0 ))[0] );
+    }
+
+    /**
+     * Test just object assertions
+     * 
+     * @throws Exception
+     */
+    public void testAssertObject() throws Exception {
+        final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.insert( "test0" );
+
+        // assert object, should add one to right memory
+        this.node.assertObject( f0,
+                                this.context,
+                                this.workingMemory );
+        assertEquals( 0,
+                      this.memory.getTupleMemory().size() );
+        assertEquals( 1,
+                      this.memory.getFactHandleMemory().size() );
+
+        // check new objects/handles still assert
+        final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.insert( "test1" );
+        this.node.assertObject( f1,
+                                this.context,
+                                this.workingMemory );
+        assertEquals( 2,
+                      this.memory.getFactHandleMemory().size() );
+
+        final Iterator it = this.memory.getFactHandleMemory().iterator( new ReteTuple( f0 ) );
+
+        final InternalFactHandle rf0 = ((FactEntry) it.next()).getFactHandle();
+        final InternalFactHandle rf1 = ((FactEntry) it.next()).getFactHandle();
+
+        assertEquals( f0,
+                      rf0 );
+        assertEquals( f1,
+                      rf1 );
+    }
+
+    /**
+     * Test assertion with both Objects and Tuples
+     * 
+     * @throws Exception
+     */
+    public void testAssertPropagations() throws Exception {
+        // assert first right object
+        final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.insert( "test0" );
+        this.node.assertObject( f0,
+                                this.context,
+                                this.workingMemory );
+
+        // assert tuple, should add left memory should be 2
+        final DefaultFactHandle f1 = new DefaultFactHandle( 1,
+                                                            "cheese" );
+        final ReteTuple tuple1 = new ReteTuple( f1 );
+        this.node.assertTuple( tuple1,
+                               this.context,
+                               this.workingMemory );
+
+        assertEquals( 1,
+                      this.sink.getAsserted().size() );
+
+        assertEquals( new ReteTuple( tuple1,
+                                     f0 ),
+                      ((Object[]) this.sink.getAsserted().get( 0 ))[0] );
+
+        final DefaultFactHandle f2 = new DefaultFactHandle( 2,
+                                                            "cheese" );
+        final ReteTuple tuple2 = new ReteTuple( f2 );
+        this.node.assertTuple( tuple2,
+                               this.context,
+                               this.workingMemory );
+
+        assertEquals( 2,
+                      this.sink.getAsserted().size() );
+        assertEquals( new ReteTuple( tuple2,
+                                     f0 ),
+                      ((Object[]) this.sink.getAsserted().get( 1 ))[0] );
+
+        final DefaultFactHandle f3 = (DefaultFactHandle) this.workingMemory.insert( "test2" );
+        this.node.assertObject( f3,
+                                this.context,
+                                this.workingMemory );
+
+        assertEquals( 4,
+                      this.sink.getAsserted().size() );
+
+        final List tuples = new ArrayList();
+        tuples.add( ((Object[]) this.sink.getAsserted().get( 2 ))[0] );
+        tuples.add( ((Object[]) this.sink.getAsserted().get( 3 ))[0] );
+
+        assertTrue( tuples.contains( new ReteTuple( tuple1,
+                                                    f3 ) ) );
+        assertTrue( tuples.contains( new ReteTuple( tuple2,
+                                                    f3 ) ) );
+    }
+
+    /**
+     * Test Tuple retraction
+     * 
+     * @throws Exception
+     * @throws RetractionException
+     */
+    public void testRetractTuple() throws Exception {
+        // setup 2 tuples 3 fact handles
+        final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.insert( "test0" );
+        this.node.assertObject( f0,
+                                this.context,
+                                this.workingMemory );
+
+        final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.insert( "test1" );
+        final ReteTuple tuple1 = new ReteTuple( f1 );
+        this.node.assertTuple( tuple1,
+                               this.context,
+                               this.workingMemory );
+
+        final DefaultFactHandle f2 = (DefaultFactHandle) this.workingMemory.insert( "test2" );
+        final ReteTuple tuple2 = new ReteTuple( f2 );
+        this.node.assertTuple( tuple2,
+                               this.context,
+                               this.workingMemory );
+
+        final DefaultFactHandle f3 = (DefaultFactHandle) this.workingMemory.insert( "test3" );
+        this.node.assertObject( f3,
+                                this.context,
+                                this.workingMemory );
+
+        final DefaultFactHandle f4 = (DefaultFactHandle) this.workingMemory.insert( "test4" );
+        this.node.assertObject( f4,
+                                this.context,
+                                this.workingMemory );
+
+        assertLength( 6,
+                      this.sink.getAsserted() );
+
+        // Double check the item is in memory
+        final BetaMemory memory = (BetaMemory) this.workingMemory.getNodeMemory( this.node );
+        assertTrue( memory.getFactHandleMemory().contains( f0 ) );
+
+        // Retract an object, check propagations  and memory
+        this.node.retractObject( f0,
+                                 this.context,
+                                 this.workingMemory );
+        assertLength( 2,
+                      this.sink.getRetracted() );
+
+        List tuples = new ArrayList();
+        tuples.add( ((Object[]) this.sink.getRetracted().get( 0 ))[0] );
+        tuples.add( ((Object[]) this.sink.getRetracted().get( 1 ))[0] );
+
+        assertTrue( tuples.contains( new ReteTuple( tuple1,
+                                                    f0 ) ) );
+        assertTrue( tuples.contains( new ReteTuple( tuple1,
+                                                    f0 ) ) );
+
+        // Now check the item  is no longer in memory
+        assertFalse( memory.getFactHandleMemory().contains( f0 ) );
+
+        this.node.retractTuple( tuple2,
+                                this.context,
+                                this.workingMemory );
+        assertEquals( 4,
+                      this.sink.getRetracted().size() );
+
+        tuples = new ArrayList();
+        tuples.add( ((Object[]) this.sink.getRetracted().get( 2 ))[0] );
+        tuples.add( ((Object[]) this.sink.getRetracted().get( 3 ))[0] );
+
+        assertTrue( tuples.contains( new ReteTuple( tuple2,
+                                                    f3 ) ) );
+        assertTrue( tuples.contains( new ReteTuple( tuple2,
+                                                    f4 ) ) );
+    }
+
+    public void testConstraintPropagations() throws Exception {
+        this.constraint.isAllowed = false;
+        // assert first right object
+        final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.insert( "test0" );
+        this.node.assertObject( f0,
+                                this.context,
+                                this.workingMemory );
+
+        // assert tuple, should add left memory should be 2
+        final DefaultFactHandle f1 = new DefaultFactHandle( 1,
+                                                            "cheese" );
+        final ReteTuple tuple1 = new ReteTuple( f1 );
+        this.node.assertTuple( tuple1,
+                               this.context,
+                               this.workingMemory );
+
+        // Should be no assertions
+        assertLength( 0,
+                      this.sink.getAsserted() );
+
+        this.node.retractObject( f0,
+                                 this.context,
+                                 this.workingMemory );
+        assertLength( 0,
+                      this.sink.getRetracted() );
+    }
+
+    public void testUpdateSink() {
+        final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
+                                                                           (ReteooRuleBase) RuleBaseFactory.newRuleBase() );
+
+        ReteooRuleBase ruleBase = ( ReteooRuleBase ) RuleBaseFactory.newRuleBase();
+        BuildContext buildContext = new BuildContext( ruleBase, ruleBase.getReteooBuilder().getIdGenerator() );
+        
+        final JoinNode joinNode = new JoinNode( 1,
+                                                this.tupleSource,
+                                                this.objectSource,
+                                                EmptyBetaConstraints.getInstance(),
+                                                buildContext );
+
+        // Add the first tuple sink and assert a tuple and object
+        // The sink has no memory
+        final MockTupleSink sink1 = new MockTupleSink( 2 );
+        joinNode.addTupleSink( sink1 );
+
+        final DefaultFactHandle f0 = new DefaultFactHandle( 0,
+                                                            "string0" );
+
+        final ReteTuple tuple1 = new ReteTuple( f0 );
+
+        joinNode.assertTuple( tuple1,
+                              this.context,
+                              workingMemory );
+
+        final String string1 = "string1";
+        final DefaultFactHandle string1Handle = new DefaultFactHandle( 1,
+                                                                       string1 );
+
+        joinNode.assertObject( string1Handle,
+                               this.context,
+                               workingMemory );
+
+        assertLength( 1,
+                      sink1.getAsserted() );
+
+        // Add the new sink, this should be updated from the re-processed
+        // joinnode memory
+        final MockTupleSink sink2 = new MockTupleSink( 3 );
+        assertLength( 0,
+                      sink2.getAsserted() );
+
+        joinNode.updateSink( sink2,
+                             this.context,
+                             workingMemory );
+
+        assertLength( 1,
+                      sink2.getAsserted() );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/LeftInputAdapterNodeTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/LeftInputAdapterNodeTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/LeftInputAdapterNodeTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,273 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.Field;
+import java.util.List;
+
+import org.drools.DroolsTestCase;
+import org.drools.RuleBaseFactory;
+import org.drools.common.BaseNode;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.reteoo.ReteooBuilder.IdGenerator;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
+import org.drools.util.FactHashTable;
+
+public class LeftInputAdapterNodeTest extends DroolsTestCase {
+    private ReteooRuleBase ruleBase;
+    private BuildContext buildContext;
+    
+    protected void setUp() throws Exception {
+        this.ruleBase = ( ReteooRuleBase ) RuleBaseFactory.newRuleBase();
+        this.buildContext = new BuildContext( ruleBase, ((ReteooRuleBase)ruleBase).getReteooBuilder().getIdGenerator() );
+    }
+    
+    public void testLeftInputAdapterNode() {
+        final MockObjectSource source = new MockObjectSource( 15 );
+        final LeftInputAdapterNode liaNode = new LeftInputAdapterNode( 23,
+                                                                       source,
+                                                                       buildContext );
+        assertEquals( 23,
+                      liaNode.getId() );
+
+        assertEquals( 0,
+                      source.getAttached() );
+        source.attach();
+        assertEquals( 1,
+                      source.getAttached() );
+    }
+
+    /**
+     * Tests the attaching of the LeftInputAdapterNode to an ObjectSource
+     * @throws Exception
+     */
+    public void testAttach() throws Exception {
+        final MockObjectSource source = new MockObjectSource( 15 );
+
+        final LeftInputAdapterNode liaNode = new LeftInputAdapterNode( 1,
+                                                                       source,
+                                                                       buildContext );
+        final Field field = ObjectSource.class.getDeclaredField( "sink" );
+        field.setAccessible( true );
+        ObjectSinkPropagator sink = (ObjectSinkPropagator) field.get( source );
+
+        assertEquals( 1,
+                      liaNode.getId() );
+        assertNotNull( sink );
+
+        liaNode.attach();
+
+        sink = (ObjectSinkPropagator) field.get( source );
+
+        assertEquals( 1,
+                      sink.getSinks().length );
+
+        assertSame( liaNode,
+                    sink.getSinks()[0] );
+    }
+
+    /**
+     * Tests the assertion of objects into LeftInputAdapterNode
+     * 
+     * @throws Exception
+     */
+    public void testAssertObjectWithoutMemory() throws Exception {
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+
+        final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
+                                                                           (ReteooRuleBase) RuleBaseFactory.newRuleBase() );
+
+        final LeftInputAdapterNode liaNode = new LeftInputAdapterNode( 1,
+                                                                       new MockObjectSource( 15 ),
+                                                                       buildContext );
+        final MockTupleSink sink = new MockTupleSink();
+        liaNode.addTupleSink( sink );
+
+        final Object string1 = "cheese";
+
+        // assert object
+        final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory.insert( string1 );
+        liaNode.assertObject( f0,
+                              context,
+                              workingMemory );
+
+        final List asserted = sink.getAsserted();
+        assertLength( 1,
+                      asserted );
+        final Tuple tuple0 = (Tuple) ((Object[]) asserted.get( 0 ))[0];
+        assertSame( string1,
+                    workingMemory.getObject( tuple0.get( 0 ) ) );
+
+    }
+
+    /**
+     * Tests the assertion of objects into LeftInputAdapterNode
+     * 
+     * @throws Exception
+     */
+    public void testAssertObjectWithMemory() throws Exception {        
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
+        final InternalWorkingMemory workingMemory = ( InternalWorkingMemory ) ruleBase.newStatefulSession();                
+
+        final LeftInputAdapterNode liaNode = new LeftInputAdapterNode( idGenerator.getNextId(),
+                                                                       new MockObjectSource( idGenerator.getNextId() ),
+                                                                       buildContext );
+
+        final MockTupleSink sink = new MockTupleSink();
+        liaNode.addTupleSink( sink );
+
+        liaNode.setObjectMemoryEnabled( true );
+
+        final Object string1 = "cheese";
+
+        // assert object
+        final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory.insert( string1 );
+        liaNode.assertObject( f0,
+                              context,
+                              workingMemory );
+
+        final List asserted = sink.getAsserted();
+        assertLength( 1,
+                      asserted );
+        final Tuple tuple0 = (Tuple) ((Object[]) asserted.get( 0 ))[0];
+        assertSame( string1,
+                    workingMemory.getObject( tuple0.get( 0 ) ) );
+
+        // check node memory
+        final FactHashTable table = (FactHashTable) workingMemory.getNodeMemory( liaNode );
+        assertEquals( 1,
+                      table.size() );
+        assertTrue( table.contains( f0 ) );
+
+        // check memory works with multiple handles
+        final DefaultFactHandle f1 = (DefaultFactHandle) workingMemory.insert( "test1" );
+        liaNode.assertObject( f1,
+                              context,
+                              workingMemory );
+
+        assertLength( 2,
+                      asserted );
+        final Tuple tuple1 = (Tuple) ((Object[]) asserted.get( 1 ))[0];
+
+        assertEquals( 2,
+                      table.size() );
+        assertTrue( table.contains( f1 ) );
+
+        assertNotSame( tuple0,
+                       tuple1 );
+
+    }
+
+    /**
+     * Tests the retractions from a LeftInputAdapterNode.
+     * Object Assertions result in tuple propagations, so we 
+     * test the remove(...) method
+     * @throws Exception
+     */
+    public void testRetractObjectWithoutMemory() throws Exception {
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+
+        final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
+                                                                           (ReteooRuleBase) RuleBaseFactory.newRuleBase() );
+
+        final MockObjectSource source = new MockObjectSource( 15 );
+
+        final LeftInputAdapterNode liaNode = new LeftInputAdapterNode( 1,
+                                                                       source,
+                                                                       buildContext );
+        final MockTupleSink sink = new MockTupleSink();
+        liaNode.addTupleSink( sink );
+
+        final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory.insert( "f1" );
+
+        // assert object 
+        liaNode.assertObject( f0,
+                              context,
+                              workingMemory );
+
+        final Tuple tuple = (Tuple) ((Object[]) sink.getAsserted().get( 0 ))[0];
+
+        liaNode.retractObject( f0,
+                               context,
+                               workingMemory );
+
+        assertEquals( tuple,
+                      ((Object[]) sink.getRetracted().get( 0 ))[0] );
+        assertNotSame( tuple,
+                       ((Object[]) sink.getRetracted().get( 0 ))[0] );
+
+    }
+
+    public void testRetractObjectWithMemory() throws Exception {
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
+        final InternalWorkingMemory workingMemory = ( InternalWorkingMemory ) ruleBase.newStatefulSession();                
+
+        final LeftInputAdapterNode liaNode = new LeftInputAdapterNode( idGenerator.getNextId(),
+                                                                       new MockObjectSource( idGenerator.getNextId() ),
+                                                                       buildContext );
+        //force liaNode to have memory
+        liaNode.setObjectMemoryEnabled( true );
+
+        final MockTupleSink sink = new MockTupleSink();
+        liaNode.addTupleSink( sink );
+
+        final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory.insert( "f1" );
+
+        // assert object
+        liaNode.assertObject( f0,
+                              context,
+                              workingMemory );
+
+        final Tuple tuple = (Tuple) ((Object[]) sink.getAsserted().get( 0 ))[0];
+
+        final FactHashTable map = (FactHashTable) workingMemory.getNodeMemory( liaNode );
+        assertTrue( map.contains( f0 ) );
+
+        liaNode.retractObject( f0,
+                               context,
+                               workingMemory );
+
+        assertFalse( map.contains( f0 ) );
+
+        assertNotSame( tuple,
+                       ((Object[]) sink.getRetracted().get( 0 ))[0] );
+
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/LogicalAssertionTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/LogicalAssertionTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/LogicalAssertionTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,899 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.Agenda;
+import org.drools.Cheese;
+import org.drools.DroolsTestCase;
+import org.drools.FactException;
+import org.drools.FactHandle;
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.RuleBaseConfiguration.LogicalOverride;
+import org.drools.base.ClassObjectType;
+import org.drools.base.ShadowProxy;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalAgenda;
+import org.drools.common.PropagationContextImpl;
+import org.drools.reteoo.ReteooBuilder.IdGenerator;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.Rule;
+import org.drools.spi.Consequence;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.PropagationContext;
+
+public class LogicalAssertionTest extends DroolsTestCase {
+    private ReteooRuleBase ruleBase;
+    private BuildContext buildContext;
+    private EntryPointNode entryPoint;
+    
+    protected void setUp() throws Exception {
+        ruleBase = ( ReteooRuleBase ) RuleBaseFactory.newRuleBase();
+        buildContext = new BuildContext( ruleBase, ((ReteooRuleBase)ruleBase).getReteooBuilder().getIdGenerator() );
+        this.entryPoint = new EntryPointNode( 0,
+                                              this.ruleBase.getRete(),
+                                              buildContext );
+        this.entryPoint.attach();
+    }
+    
+    public void testSingleLogicalRelationship() throws Exception {
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
+
+        final Rete rete = ruleBase.getRete();
+        // create a RuleBase with a single ObjectTypeNode we attach a
+        // MockObjectSink so we can detect assertions and retractions
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( idGenerator.getNextId(),
+                                                                  this.entryPoint,
+                                                                  new ClassObjectType( String.class ),
+                                                                  buildContext );
+        objectTypeNode.attach();
+        final MockObjectSink sink = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink );
+
+        final Rule rule1 = new Rule( "test-rule1" );
+        final RuleTerminalNode node = new RuleTerminalNode( idGenerator.getNextId(),
+                                                            new MockTupleSource( idGenerator.getNextId() ),
+                                                            rule1,
+                                                            rule1.getLhs(),
+                                                            buildContext );
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+        final Consequence consequence = new Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory workingMemory) {
+                // do nothing
+            }
+        };
+
+        rule1.setConsequence( consequence );
+
+        final DefaultFactHandle handle1 = (DefaultFactHandle) workingMemory.insert( "o1" );
+        final ReteTuple tuple1 = new ReteTuple( handle1 );
+
+        final PropagationContext context1 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        null,
+                                                                        null );
+
+        // Test single activation for a single logical assertions
+        node.assertTuple( tuple1,
+                          context1,
+                          workingMemory );
+
+        final String logicalString = new String( "logical" );
+        FactHandle logicalHandle = workingMemory.insert( logicalString,
+                                                         false,
+                                                         true,
+                                                         rule1,
+                                                         tuple1.getActivation() );
+        // Retract the tuple and test the logically asserted fact was also retracted
+        node.retractTuple( tuple1,
+                           context1,
+                           workingMemory );
+
+        workingMemory.executeQueuedActions();
+
+        assertLength( 1,
+                      sink.getRetracted() );
+
+        Object[] values = (Object[]) sink.getRetracted().get( 0 );
+
+        assertSame( logicalHandle,
+                    values[0] );
+
+        // Test single activation for a single logical assertions. This also
+        // tests that logical assertions live on after the related Activation
+        // has fired.
+        node.assertTuple( tuple1,
+                          context1,
+                          workingMemory );
+        logicalHandle = workingMemory.insert( logicalString,
+                                              false,
+                                              true,
+                                              rule1,
+                                              tuple1.getActivation() );
+
+        agenda.fireNextItem( null );
+
+        node.retractTuple( tuple1,
+                           context1,
+                           workingMemory );
+
+        workingMemory.executeQueuedActions();
+
+        assertLength( 2,
+                      sink.getRetracted() );
+
+        values = (Object[]) sink.getRetracted().get( 1 );
+
+        assertSame( logicalHandle,
+                    values[0] );
+    }
+
+    public void testEqualsMap() throws Exception {
+        // create a RuleBase with a single ObjectTypeNode we attach a
+        // MockObjectSink so w can detect assertions and retractions
+        final Rule rule1 = new Rule( "test-rule1" );
+
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
+
+        final Rete rete = ruleBase.getRete();
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( idGenerator.getNextId(),
+                                                                  this.entryPoint,
+                                                                  new ClassObjectType( String.class ),
+                                                                  buildContext );
+        objectTypeNode.attach();
+        final MockObjectSink sink = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink );
+
+        final RuleTerminalNode node = new RuleTerminalNode( idGenerator.getNextId(),
+                                                            new MockTupleSource( idGenerator.getNextId() ),
+                                                            rule1,
+                                                            rule1.getLhs(),
+                                                            buildContext );
+
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final Agenda agenda = workingMemory.getAgenda();
+
+        final Consequence consequence = new Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory workingMemory) {
+                // do nothing
+            }
+        };
+        rule1.setConsequence( consequence );
+
+        final DefaultFactHandle handle1 = new DefaultFactHandle( 1,
+                                                                 "cheese" );
+        final ReteTuple tuple1 = new ReteTuple( handle1 );
+
+        final PropagationContext context1 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        null,
+                                                                        null );
+
+        // Test single activation for a single logical assertions
+        node.assertTuple( tuple1,
+                          context1,
+                          workingMemory );
+
+        final String logicalString1 = new String( "logical" );
+        FactHandle logicalHandle1 = workingMemory.insert( logicalString1,
+                                                          false,
+                                                          true,
+                                                          rule1,
+                                                          tuple1.getActivation() );
+
+        final String logicalString2 = new String( "logical" );
+        FactHandle logicalHandle2 = workingMemory.insert( logicalString2,
+                                                          false,
+                                                          true,
+                                                          rule1,
+                                                          tuple1.getActivation() );
+
+        assertSame( logicalHandle1,
+                    logicalHandle2 );
+
+        // little sanity check using normal assert
+        logicalHandle1 = workingMemory.insert( logicalString1 );
+        logicalHandle2 = workingMemory.insert( logicalString2 );
+
+        // If assert behavior in working memory is IDENTITY, 
+        // returned handles must not be the same 
+        if ( RuleBaseConfiguration.AssertBehaviour.IDENTITY == ((ReteooRuleBase) ruleBase).getConfiguration().getAssertBehaviour() ) {
+
+            assertNotSame( logicalHandle1,
+                           logicalHandle2 );
+        } else {
+            // in case behavior is EQUALS, handles should be the same
+            assertSame( logicalHandle1,
+                        logicalHandle2 );
+        }
+    }
+
+    /**
+     * This tests that Stated asserts always take precedent
+     * 
+     * @throws Exception
+     */
+    public void testStatedOverrideDiscard() throws Exception {
+        // create a RuleBase with a single ObjectTypeNode we attach a
+        // MockObjectSink so we can detect assertions and retractions
+        final Rule rule1 = new Rule( "test-rule1" );
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
+
+        final Rete rete = ruleBase.getRete();
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( idGenerator.getNextId(),
+                                                                  this.entryPoint,
+                                                                  new ClassObjectType( String.class ),
+                                                                  buildContext );
+        objectTypeNode.attach();
+        final MockObjectSink sink = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink );
+        final RuleTerminalNode node = new RuleTerminalNode( idGenerator.getNextId(),
+                                                            new MockTupleSource( idGenerator.getNextId() ),
+                                                            rule1,
+                                                            rule1.getLhs(),
+                                                            buildContext  );
+
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final Agenda agenda = workingMemory.getAgenda();
+
+        final Consequence consequence = new Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory workingMemory) {
+                // do nothing
+            }
+        };
+        rule1.setConsequence( consequence );
+
+        final DefaultFactHandle handle1 = new DefaultFactHandle( 1,
+                                                                 "cheese" );
+        final ReteTuple tuple1 = new ReteTuple( handle1 );
+
+        final PropagationContext context1 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        null,
+                                                                        null );
+
+        // Test that a STATED assertion overrides a logical assertion
+        node.assertTuple( tuple1,
+                          context1,
+                          workingMemory );
+
+        String logicalString1 = new String( "logical" );
+        FactHandle logicalHandle1 = workingMemory.insert( logicalString1,
+                                                          false,
+                                                          true,
+                                                          rule1,
+                                                          tuple1.getActivation() );
+
+        // This assertion is stated and should override any previous justified
+        // "equals" objects.
+        String logicalString2 = new String( "logical" );
+        FactHandle logicalHandle2 = workingMemory.insert( logicalString2 );
+
+        node.retractTuple( tuple1,
+                           context1,
+                           workingMemory );
+
+        assertLength( 0,
+                      sink.getRetracted() );
+
+        //  we override and discard the original logical object
+        assertSame( logicalHandle2,
+                    logicalHandle1 );
+
+        // so while new STATED assertion is equal
+        assertEquals( logicalString1,
+                      workingMemory.getObject( logicalHandle2 ) );
+        // they are not identity same
+        assertNotSame( logicalString1,
+                       workingMemory.getObject( logicalHandle2 ) );
+
+        // Test that a logical assertion cannot override a STATED assertion
+        node.assertTuple( tuple1,
+                          context1,
+                          workingMemory );
+
+        logicalString2 = new String( "logical" );
+        logicalHandle2 = workingMemory.insert( logicalString2 );
+
+        // This logical assertion will be ignored as there is already
+        // an equals STATED assertion.
+        logicalString1 = new String( "logical" );
+        logicalHandle1 = workingMemory.insert( logicalString1,
+                                               false,
+                                               true,
+                                               rule1,
+                                               tuple1.getActivation() );
+
+        assertNull( logicalHandle1 );
+
+        // Already identify same so return previously assigned handle
+        logicalHandle1 = workingMemory.insert( logicalString2,
+                                               false,
+                                               false,
+                                               rule1,
+                                               tuple1.getActivation() );
+        // return the matched handle
+
+        assertSame( logicalHandle2,
+                    logicalHandle1 );
+
+        node.retractTuple( tuple1,
+                           context1,
+                           workingMemory );
+
+        assertLength( 0,
+                      sink.getRetracted() );
+
+        // Should keep the same handle when overriding
+        assertSame( logicalHandle1,
+                    logicalHandle2 );
+
+        // so while new STATED assertion is equal
+        assertEquals( logicalString1,
+                      workingMemory.getObject( logicalHandle2 ) );
+
+        // they are not identity same
+        assertNotSame( logicalString1,
+                       workingMemory.getObject( logicalHandle2 ) );
+
+    }
+
+    /**
+     * This tests that Stated asserts always take precedent
+     * 
+     * @throws Exception
+     */
+    public void testStatedOverridePreserve() throws Exception {
+        // create a RuleBase with a single ObjectTypeNode we attach a
+        // MockObjectSink so we can detect assertions and retractions
+        final Rule rule1 = new Rule( "test-rule1" );
+        RuleBaseConfiguration conf = new RuleBaseConfiguration();
+        conf.setLogicalOverride( LogicalOverride.PRESERVE );
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase(conf);
+        
+        BuildContext buildContext = new BuildContext( ruleBase, ruleBase.getReteooBuilder().getIdGenerator() );
+        
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
+
+        final Rete rete = ruleBase.getRete();
+        final EntryPointNode entryPoint = new EntryPointNode( 0,
+                                                              rete,
+                                                              buildContext );
+        entryPoint.attach();
+        
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( idGenerator.getNextId(),
+                                                                  entryPoint,
+                                                                  new ClassObjectType( String.class ),
+                                                                  buildContext );
+        objectTypeNode.attach();
+        final MockObjectSink sink = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink );
+        final RuleTerminalNode node = new RuleTerminalNode( idGenerator.getNextId(),
+                                                            new MockTupleSource( idGenerator.getNextId() ),
+                                                            rule1,
+                                                            rule1.getLhs(),
+                                                            buildContext  );
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final Agenda agenda = workingMemory.getAgenda();
+
+        final Consequence consequence = new Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory workingMemory) {
+                // do nothing
+            }
+        };
+        rule1.setConsequence( consequence );
+
+        final DefaultFactHandle handle1 = new DefaultFactHandle( 1,
+                                                                 "cheese" );
+        final ReteTuple tuple1 = new ReteTuple( handle1 );
+
+        final PropagationContext context1 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        null,
+                                                                        null );
+
+        // Test that a STATED assertion overrides a logical assertion
+        node.assertTuple( tuple1,
+                          context1,
+                          workingMemory );
+
+        final String logicalString1 = new String( "logical" );
+        final FactHandle logicalHandle1 = workingMemory.insert( logicalString1,
+                                                                false,
+                                                                true,
+                                                                rule1,
+                                                                tuple1.getActivation() );
+
+        // This assertion is stated and should override any previous justified
+        // "equals" objects.
+        String logicalString2 = new String( "logical" );
+        FactHandle logicalHandle2 = workingMemory.insert( logicalString2 );
+
+        node.retractTuple( tuple1,
+                           context1,
+                           workingMemory );
+
+        assertLength( 0,
+                      sink.getRetracted() );
+
+        assertNotSame( logicalHandle2,
+                       logicalHandle1 );
+
+        // so while new STATED assertion is equal
+        assertEquals( workingMemory.getObject( logicalHandle1 ),
+                      workingMemory.getObject( logicalHandle2 ) );
+
+        // they are not identity same
+        assertNotSame( workingMemory.getObject( logicalHandle1 ),
+                       workingMemory.getObject( logicalHandle2 ) );
+
+        // Test that a logical assertion cannot override a STATED assertion
+        node.assertTuple( tuple1,
+                          context1,
+                          workingMemory );
+
+        logicalString2 = new String( "logical" );
+        logicalHandle2 = workingMemory.insert( logicalString2 );
+    }
+
+    public void testRetract() throws Exception {
+        // create a RuleBase with a single ObjectTypeNode we attach a
+        // MockObjectSink so we can detect assertions and retractions
+        final Rule rule1 = new Rule( "test-rule1" );
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
+
+        final Rete rete = ruleBase.getRete();
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( idGenerator.getNextId(),
+                                                                  this.entryPoint,
+                                                                  new ClassObjectType( String.class ),
+                                                                  buildContext );
+        objectTypeNode.attach();
+        final MockObjectSink sink = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink );
+        final RuleTerminalNode node = new RuleTerminalNode( idGenerator.getNextId(),
+                                                            new MockTupleSource( idGenerator.getNextId() ),
+                                                            rule1,
+                                                            rule1.getLhs(),
+                                                            buildContext  );
+
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final Consequence consequence = new Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory workingMemory) {
+                // do nothing
+            }
+        };
+
+        // create the first activation which will justify the fact "logical"
+        rule1.setConsequence( consequence );
+
+        final DefaultFactHandle handle1 = new DefaultFactHandle( 1,
+                                                                 "cheese" );
+        final ReteTuple tuple1 = new ReteTuple( handle1 );
+
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+
+        node.assertTuple( tuple1,
+                          context,
+                          workingMemory );
+
+        // Assert the logical "logical" fact
+        final String logicalString1 = new String( "logical" );
+        final FactHandle logicalHandle1 = workingMemory.insert( logicalString1,
+                                                                false,
+                                                                true,
+                                                                rule1,
+                                                                tuple1.getActivation() );
+
+        // create the second activation to justify the "logical" fact
+        final Rule rule2 = new Rule( "test-rule2" );
+        final RuleTerminalNode node2 = new RuleTerminalNode( idGenerator.getNextId(),
+                                                             new MockTupleSource( 3 ),
+                                                             rule2,
+                                                             rule2.getLhs(),
+                                                             buildContext  );
+        rule2.setConsequence( consequence );
+
+        final DefaultFactHandle handle2 = new DefaultFactHandle( 2,
+                                                                 "cheese" );
+        final ReteTuple tuple2 = new ReteTuple( handle2 );
+
+        node.assertTuple( tuple2,
+                          context,
+                          workingMemory );
+
+        node2.assertTuple( tuple2,
+                           context,
+                           workingMemory );
+
+        // Assert the logical "logical" fact
+        final String logicalString2 = new String( "logical" );
+        final FactHandle logicalHandle2 = workingMemory.insert( logicalString2,
+                                                                false,
+                                                                true,
+                                                                rule2,
+                                                                tuple2.getActivation() );
+
+        // "logical" should only appear once
+        assertLength( 1,
+                      workingMemory.getTruthMaintenanceSystem().getJustifiedMap().values() );
+
+        // retract the logical object
+        workingMemory.retract( logicalHandle2 );
+
+        // The logical object should never appear
+        assertLength( 0,
+                      workingMemory.getTruthMaintenanceSystem().getJustifiedMap().values() );
+
+    }
+
+    public void testMultipleLogicalRelationships() throws FactException {
+        final Rule rule1 = new Rule( "test-rule1" );
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
+
+        final Rete rete = ruleBase.getRete();
+
+        // Create a RuleBase with a single ObjectTypeNode we attach a
+        // MockObjectSink so we can detect assertions and retractions
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( idGenerator.getNextId(),
+                                                                  this.entryPoint,
+                                                                  new ClassObjectType( String.class ),
+                                                                  buildContext );
+        objectTypeNode.attach();
+        final MockObjectSink sink = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink );
+        final RuleTerminalNode node = new RuleTerminalNode( idGenerator.getNextId(),
+                                                            new MockTupleSource(  idGenerator.getNextId() ),
+                                                            rule1,
+                                                            rule1.getLhs(),
+                                                            buildContext  );
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final Agenda agenda = workingMemory.getAgenda();
+
+        final Consequence consequence = new Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory workingMemory) {
+                // do nothing
+            }
+        };
+
+        // Create first justifier
+        rule1.setConsequence( consequence );
+
+        final DefaultFactHandle handle1 = new DefaultFactHandle( 1,
+                                                                 "cheese" );
+        final ReteTuple tuple1 = new ReteTuple( handle1 );
+
+        final PropagationContext context1 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        null,
+                                                                        null );
+        // get the activation onto the agenda
+        node.assertTuple( tuple1,
+                          context1,
+                          workingMemory );
+
+        // Create the second justifer
+        final Rule rule2 = new Rule( "test-rule2" );
+        final RuleTerminalNode node2 = new RuleTerminalNode(  idGenerator.getNextId(),
+                                                             new MockTupleSource(  idGenerator.getNextId() ),
+                                                             rule2,
+                                                             rule2.getLhs(),
+                                                             buildContext  );
+        rule2.setConsequence( consequence );
+
+        final DefaultFactHandle handle2 = new DefaultFactHandle( 2,
+                                                                 "cheese" );
+        final ReteTuple tuple2 = new ReteTuple( handle2 );
+
+        final PropagationContext context2 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        null,
+                                                                        null );
+
+        // get the activations onto the agenda
+        node2.assertTuple( tuple2,
+                           context2,
+                           workingMemory );
+
+        // Create the first justifieable relationship
+        final String logicalString1 = new String( "logical" );
+        final FactHandle logicalHandle1 = workingMemory.insert( logicalString1,
+                                                                false,
+                                                                true,
+                                                                rule1,
+                                                                tuple1.getActivation() );
+
+        // Create the second justifieable relationship
+        final String logicalString2 = new String( "logical" );
+        final FactHandle logicalHandle2 = workingMemory.insert( logicalString2,
+                                                                false,
+                                                                true,
+                                                                rule2,
+                                                                tuple2.getActivation() );
+
+        // "logical" should only appear once
+        assertLength( 1,
+                      workingMemory.getTruthMaintenanceSystem().getJustifiedMap().values() );
+
+        // Now lets cancel the first activation
+        node2.retractTuple( tuple2,
+                            context2,
+                            workingMemory );
+
+        workingMemory.executeQueuedActions();
+
+        // because this logical fact has two relationships it shouldn't retract yet
+        assertLength( 0,
+                      sink.getRetracted() );
+
+        // check "logical" is still in the system
+        assertLength( 1,
+                      workingMemory.getTruthMaintenanceSystem().getJustifiedMap().values() );
+
+        // now remove that final justification
+        node.retractTuple( tuple1,
+                           context1,
+                           workingMemory );
+
+        workingMemory.executeQueuedActions();
+
+        // Should cause the logical fact to be retracted
+        assertLength( 1,
+                      sink.getRetracted() );
+
+        // "logical" fact should no longer be in the system
+        assertLength( 0,
+                      workingMemory.getTruthMaintenanceSystem().getJustifiedMap().values() );
+    }
+
+    /**
+     * This tests that when multiple not identical, but equals facts, are asserted
+     * into WM, only when all are removed, a logical assert will succeed 
+     * 
+     * @throws Exception
+     */
+    public void testMultipleAssert() throws Exception {
+        // create a RuleBase with a single ObjectTypeNode we attach a
+        // MockObjectSink so we can detect assertions and retractions
+        final Rule rule1 = new Rule( "test-rule1" );
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
+
+        final Rete rete = ruleBase.getRete();
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( idGenerator.getNextId(),
+                                                                  this.entryPoint,
+                                                                  new ClassObjectType( String.class ),
+                                                                  buildContext );
+        objectTypeNode.attach();
+        final MockObjectSink sink = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink );
+        final RuleTerminalNode node = new RuleTerminalNode( idGenerator.getNextId(),
+                                                            new MockTupleSource( idGenerator.getNextId() ),
+                                                            rule1,
+                                                            rule1.getLhs(),
+                                                            buildContext  );
+
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final Agenda agenda = workingMemory.getAgenda();
+
+        final Consequence consequence = new Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory workingMemory) {
+                // do nothing
+            }
+        };
+        rule1.setConsequence( consequence );
+
+        final DefaultFactHandle handle1 = new DefaultFactHandle( 1,
+                                                                 "cheese" );
+        final ReteTuple tuple1 = new ReteTuple( handle1 );
+
+        final PropagationContext context1 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        null,
+                                                                        null );
+
+        // Assert multiple stated objects
+        node.assertTuple( tuple1,
+                          context1,
+                          workingMemory );
+
+        final String statedString1 = new String( "logical" );
+        final FactHandle statedHandle1 = workingMemory.insert( statedString1 );
+
+        final String statedString2 = new String( "logical" );
+        final FactHandle statedHandle2 = workingMemory.insert( statedString2 );
+
+        // This assertion is logical should fail as there is previous stated objects
+        final String logicalString3 = new String( "logical" );
+        FactHandle logicalHandle3 = workingMemory.insert( logicalString3,
+                                                          false,
+                                                          true,
+                                                          rule1,
+                                                          tuple1.getActivation() );
+
+        // Checks that previous LogicalAssert failed 
+        assertNull( logicalHandle3 );
+
+        // If assert behavior in working memory is IDENTITY, 
+        // we need to retract object 2 times before being able to 
+        // succesfully logically assert a new fact
+        if ( RuleBaseConfiguration.AssertBehaviour.IDENTITY == ((ReteooRuleBase) ruleBase).getConfiguration().getAssertBehaviour() ) {
+
+            workingMemory.retract( statedHandle2 );
+
+            logicalHandle3 = workingMemory.insert( logicalString3,
+                                                   false,
+                                                   true,
+                                                   rule1,
+                                                   tuple1.getActivation() );
+
+            // Checks that previous LogicalAssert failed 
+            assertNull( logicalHandle3 );
+        }
+
+        workingMemory.retract( statedHandle1 );
+
+        logicalHandle3 = workingMemory.insert( logicalString3,
+                                               false,
+                                               true,
+                                               rule1,
+                                               tuple1.getActivation() );
+
+        // Checks that previous LogicalAssert succeeded as there are no more
+        // stated strings in the working memory
+        assertNotNull( logicalHandle3 );
+
+    }
+
+    /**
+     * This test checks that truth maintenance is correctly maintained for modified objects 
+     */
+    public void testMutableObject() {
+        // create a RuleBase with a single ObjectTypeNode we attach a
+        // MockObjectSink so we can detect assertions and retractions
+        final Rule rule1 = new Rule( "test-rule1" );
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
+
+        final Rete rete = ruleBase.getRete();
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( idGenerator.getNextId(),
+                                                                  this.entryPoint,
+                                                                  new ClassObjectType( String.class ),
+                                                                  buildContext );
+        objectTypeNode.attach();
+        final MockObjectSink sink = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink );
+        final RuleTerminalNode node = new RuleTerminalNode( idGenerator.getNextId(),
+                                                            new MockTupleSource( idGenerator.getNextId() ),
+                                                            rule1,
+                                                            rule1.getLhs(),
+                                                            buildContext  );
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final Agenda agenda = workingMemory.getAgenda();
+
+        final Consequence consequence = new Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory workingMemory) {
+                // do nothing
+            }
+        };
+        rule1.setConsequence( consequence );
+
+        final DefaultFactHandle handle1 = new DefaultFactHandle( 1,
+                                                                 "cheese" );
+        final ReteTuple tuple1 = new ReteTuple( handle1 );
+
+        final PropagationContext context1 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        null,
+                                                                        null );
+
+        // Test that a STATED assertion overrides a logical assertion
+        node.assertTuple( tuple1,
+                          context1,
+                          workingMemory );
+
+        final Cheese cheese = new Cheese( "brie",
+                                          10 );
+        final FactHandle cheeseHandle = workingMemory.insert( cheese,
+                                                              false,
+                                                              true,
+                                                              rule1,
+                                                              tuple1.getActivation() );
+
+        cheese.setType( "cheddar" );
+        cheese.setPrice( 20 );
+
+        assertEquals( 1,
+                      workingMemory.getTruthMaintenanceSystem().getJustifiedMap().size() );
+        assertEquals( 1,
+                      workingMemory.getTruthMaintenanceSystem().getAssertMap().size() );
+
+        workingMemory.retract( cheeseHandle );
+
+        assertEquals( 0,
+                      workingMemory.getTruthMaintenanceSystem().getJustifiedMap().size() );
+        assertEquals( 0,
+                      workingMemory.getTruthMaintenanceSystem().getAssertMap().size() );
+    }
+
+    private Object unwrapShadow(Object object) {
+        if ( object instanceof ShadowProxy ) {
+            return ((ShadowProxy) object).getShadowedObject();
+        } else {
+            return object;
+        }
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockAccumulator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockAccumulator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockAccumulator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.drools.reteoo;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.drools.WorkingMemory;
+import org.drools.common.InternalFactHandle;
+import org.drools.rule.Declaration;
+import org.drools.spi.Accumulator;
+import org.drools.spi.Tuple;
+
+/**
+ * A Mock accumulate object.
+ * 
+ * @author etirelli
+ *
+ */
+public class MockAccumulator
+    implements
+    Accumulator {
+
+    private static final long serialVersionUID = 400L;
+
+    private Tuple             leftTuple        = null;
+    private List              matchingObjects  = Collections.EMPTY_LIST;
+    private WorkingMemory     workingMemory    = null;
+
+    public Tuple getLeftTuple() {
+        return this.leftTuple;
+    }
+
+    public List getMatchingObjects() {
+        return this.matchingObjects;
+    }
+
+    public WorkingMemory getWorkingMemory() {
+        return this.workingMemory;
+    }
+    
+    public Object createContext() {
+        return this;
+    }
+
+    public void init(Object workingMemoryContext,
+                     Object context,
+                     Tuple leftTuple,
+                     Declaration[] declarations,
+                     WorkingMemory workingMemory) throws Exception {
+        this.leftTuple = leftTuple;
+        this.matchingObjects = new ArrayList();
+        this.workingMemory = workingMemory;
+    }
+
+    public void accumulate(Object workingMemoryContext,
+                           Object context,
+                           Tuple leftTuple,
+                           InternalFactHandle handle,
+                           Declaration[] declarations,
+                           Declaration[] innerDeclarations,
+                           WorkingMemory workingMemory) throws Exception {
+        this.matchingObjects.add( handle.getObject() );
+    }
+
+    public Object getResult(Object workingMemoryContext,
+                            Object context,
+                            Tuple leftTuple,
+                            Declaration[] declarations,
+                            WorkingMemory workingMemory) throws Exception {
+        return this.matchingObjects;
+    }
+
+    public void reverse(Object workingMemoryContext,
+                        Object context,
+                        Tuple leftTuple,
+                        InternalFactHandle handle,
+                        Declaration[] declarations,
+                        Declaration[] innerDeclarations,
+                        WorkingMemory workingMemory) throws Exception {
+        // nothing to do yet
+    }
+
+    public boolean supportsReverse() {
+        return false;
+    }
+
+    public Object createWorkingMemoryContext() {
+        return null;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockEvalCondition.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockEvalCondition.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockEvalCondition.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,68 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.WorkingMemory;
+import org.drools.rule.Declaration;
+import org.drools.rule.EvalCondition;
+import org.drools.spi.EvalExpression;
+import org.drools.spi.Tuple;
+
+public class MockEvalCondition extends EvalCondition {
+
+    /**
+     * 
+     */
+    private static final long    serialVersionUID = 400L;
+
+    private Boolean              isAllowed;
+
+    private final EvalExpression expression       = new EvalExpression() {
+                                                      /**
+                                                       * 
+                                                       */
+                                                      private static final long serialVersionUID = 400L;
+
+                                                      public boolean evaluate(Tuple tuple,
+                                                                              Declaration[] requiredDeclarations,
+                                                                              WorkingMemory workingMemory) {
+                                                          return MockEvalCondition.this.isAllowed.booleanValue();
+                                                      }
+                                                  };
+
+    public MockEvalCondition(final boolean isAllowed) {
+        this( isAllowed,
+              null );
+    }
+
+    public MockEvalCondition(final boolean isAllowed,
+                             final Declaration[] requiredDeclarations) {
+        super( requiredDeclarations );
+        setEvalExpression( this.expression );
+        setIsAllowed( isAllowed );
+    }
+
+    public MockEvalCondition(final EvalExpression eval,
+                             final Declaration[] requiredDeclarations) {
+        super( eval,
+               requiredDeclarations );
+    }
+
+    public void setIsAllowed(final boolean isAllowed) {
+        this.isAllowed = new Boolean( isAllowed );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockObjectSink.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockObjectSink.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockObjectSink.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,100 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+
+public class MockObjectSink
+    implements
+    ObjectSinkNode {
+    private final List     asserted  = new ArrayList();
+    private final List     retracted = new ArrayList();
+
+    private ObjectSinkNode previousObjectSinkNode;
+    private ObjectSinkNode nextObjectSinkNode;
+
+    public void assertObject(final InternalFactHandle handle,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+        this.asserted.add( new Object[]{handle, context, workingMemory} );
+    }
+
+    public void retractObject(final InternalFactHandle handle,
+                              final PropagationContext context,
+                              final InternalWorkingMemory workingMemory) {
+        this.retracted.add( new Object[]{handle, context, workingMemory} );
+    }
+
+    public List getAsserted() {
+        return this.asserted;
+    }
+
+    public List getRetracted() {
+        return this.retracted;
+    }
+
+    /**
+     * Returns the next node
+     * @return
+     *      The next ObjectSinkNode
+     */
+    public ObjectSinkNode getNextObjectSinkNode() {
+        return this.nextObjectSinkNode;
+    }
+
+    /**
+     * Sets the next node 
+     * @param next
+     *      The next ObjectSinkNode
+     */
+    public void setNextObjectSinkNode(final ObjectSinkNode next) {
+        this.nextObjectSinkNode = next;
+    }
+
+    /**
+     * Returns the previous node
+     * @return
+     *      The previous ObjectSinkNode
+     */
+    public ObjectSinkNode getPreviousObjectSinkNode() {
+        return this.previousObjectSinkNode;
+    }
+
+    /**
+     * Sets the previous node 
+     * @param previous
+     *      The previous ObjectSinkNode
+     */
+    public void setPreviousObjectSinkNode(final ObjectSinkNode previous) {
+        this.previousObjectSinkNode = previous;
+    }
+
+    public boolean isObjectMemoryEnabled() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public void setObjectMemoryEnabled(boolean objectMemoryOn) {
+        // TODO Auto-generated method stub
+        
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockObjectSource.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockObjectSource.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockObjectSource.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,85 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.drools.common.BaseNode;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+
+public class MockObjectSource extends ObjectSource {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    private int               attached;
+
+    private int               updated;
+
+    private List              facts;
+
+    public MockObjectSource(final int id) {
+        super( id );
+        this.facts = new ArrayList();
+    }
+
+    public void attach() {
+        this.attached++;
+
+    }
+
+    public int getAttached() {
+        return this.attached;
+    }
+
+    public int getUdated() {
+        return this.updated;
+    }
+
+    public void addFact(final InternalFactHandle handle) {
+        this.facts.add( handle );
+    }
+
+    public void updateSink(final ObjectSink sink,
+                           final PropagationContext context,
+                           final InternalWorkingMemory workingMemory) {
+        this.updated++;
+        for ( final Iterator it = this.facts.iterator(); it.hasNext(); ) {
+            final InternalFactHandle handle = (InternalFactHandle) it.next();
+            sink.assertObject( handle,
+                               context,
+                               workingMemory );
+        }
+    }
+
+    public void remove(ReteooBuilder builder,
+                       final BaseNode node, final InternalWorkingMemory[] workingMemories) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void attach(final InternalWorkingMemory[] workingMemories) {
+        // TODO Auto-generated method stub
+
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockTupleSink.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockTupleSink.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockTupleSink.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,162 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
+import org.drools.FactException;
+import org.drools.RuleBaseConfiguration;
+import org.drools.common.BaseNode;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.NodeMemory;
+import org.drools.spi.PropagationContext;
+
+public class MockTupleSink extends TupleSource
+    implements
+    TupleSinkNode,
+    NodeMemory {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+    private final List        asserted         = new ArrayList();
+    private final List        retracted        = new ArrayList();
+
+    private TupleSinkNode     previousTupleSinkNode;
+    private TupleSinkNode     nextTupleSinkNode;
+
+    public MockTupleSink() {
+        super( 0 );
+    }
+
+    public MockTupleSink(final int id) {
+        super( id );
+    }
+
+    public void assertTuple(final ReteTuple tuple,
+                            final PropagationContext context,
+                            final InternalWorkingMemory workingMemory) {
+        this.asserted.add( new Object[]{tuple, context, workingMemory} );
+
+    }
+
+    public void retractTuple(final ReteTuple tuple,
+                             final PropagationContext context,
+                             final InternalWorkingMemory workingMemory) {
+        this.retracted.add( new Object[]{tuple, context, workingMemory} );
+
+    }
+
+    public List getAsserted() {
+        return this.asserted;
+    }
+
+    public List getRetracted() {
+        return this.retracted;
+    }
+
+    public void ruleAttached() {
+        // TODO Auto-generated method stub
+    }
+
+    public int getId() {
+        return this.id;
+    }
+
+    public Object createMemory(final RuleBaseConfiguration config) {
+        return new HashMap();
+    }
+
+    public void attach() {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void updateSink(final TupleSink sink,
+                           final PropagationContext context,
+                           final InternalWorkingMemory workingMemory) throws FactException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void remove(ReteooBuilder builder,
+                       final BaseNode node, final InternalWorkingMemory[] workingMemories) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void attach(final InternalWorkingMemory[] workingMemories) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public List getPropagatedTuples(final ReteooWorkingMemory workingMemory,
+                                    final TupleSink sink) {
+        // TODO Auto-generated method stub
+        return Collections.EMPTY_LIST;
+    }
+
+    /**
+     * Returns the next node
+     * @return
+     *      The next TupleSinkNode
+     */
+    public TupleSinkNode getNextTupleSinkNode() {
+        return this.nextTupleSinkNode;
+    }
+
+    /**
+     * Sets the next node 
+     * @param next
+     *      The next TupleSinkNode
+     */
+    public void setNextTupleSinkNode(final TupleSinkNode next) {
+        this.nextTupleSinkNode = next;
+    }
+
+    /**
+     * Returns the previous node
+     * @return
+     *      The previous TupleSinkNode
+     */
+    public TupleSinkNode getPreviousTupleSinkNode() {
+        return this.previousTupleSinkNode;
+    }
+
+    /**
+     * Sets the previous node 
+     * @param previous
+     *      The previous TupleSinkNode
+     */
+    public void setPreviousTupleSinkNode(final TupleSinkNode previous) {
+        this.previousTupleSinkNode = previous;
+    }
+
+    public boolean isTupleMemoryEnabled() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public void setTupleMemoryEnabled(boolean tupleMemoryEnabled) {
+        // TODO Auto-generated method stub
+        
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockTupleSource.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockTupleSource.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/MockTupleSource.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,67 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.common.BaseNode;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+
+public class MockTupleSource extends TupleSource {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    private int               attached;
+
+    private int               updated;
+
+    public MockTupleSource(final int id) {
+        super( id );
+    }
+
+    public void attach() {
+        this.attached++;
+    }
+
+    public int getAttached() {
+        return this.sink.getSinks().length;
+    }
+
+    public int getUdated() {
+        return this.updated;
+    }
+
+    public void updateSink(final TupleSink sink,
+                           final PropagationContext context,
+                           final InternalWorkingMemory workingMemory) {
+        this.updated++;
+    }
+
+    public void remove(ReteooBuilder builder,
+                       final BaseNode node, final InternalWorkingMemory[] workingMemories) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void attach(final InternalWorkingMemory[] workingMemories) {
+        // TODO Auto-generated method stub
+
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/NotNodeTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/NotNodeTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/NotNodeTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,379 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.beans.IntrospectionException;
+
+import junit.framework.Assert;
+
+import org.drools.Cheese;
+import org.drools.DroolsTestCase;
+import org.drools.FactException;
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuleBaseFactory;
+import org.drools.common.BetaConstraints;
+import org.drools.common.DefaultBetaConstraints;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.EmptyBetaConstraints;
+import org.drools.common.PropagationContextImpl;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.Rule;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.spi.MockConstraint;
+import org.drools.spi.PropagationContext;
+
+public class NotNodeTest extends DroolsTestCase {
+    Rule                  rule;
+    PropagationContext    context;
+    ReteooWorkingMemory   workingMemory;
+    MockObjectSource      objectSource;
+    MockTupleSource       tupleSource;
+    MockTupleSink         sink;
+    NotNode               node;
+    RightInputAdapterNode ria;
+    BetaMemory            memory;
+    MockConstraint        constraint = new MockConstraint();
+
+    /**
+     * Setup the BetaNode used in each of the tests
+     * @throws IntrospectionException 
+     */
+    public void setUp() throws IntrospectionException {
+        this.rule = new Rule( "test-rule" );
+        this.context = new PropagationContextImpl( 0,
+                                                   PropagationContext.ASSERTION,
+                                                   null,
+                                                   null );
+        this.workingMemory = new ReteooWorkingMemory( 1,
+                                                      (ReteooRuleBase) RuleBaseFactory.newRuleBase() );
+
+        final RuleBaseConfiguration configuration = new RuleBaseConfiguration();
+
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ruleBase.getReteooBuilder().getIdGenerator() );
+
+        // string1Declaration is bound to pattern 3 
+        this.node = new NotNode( 15,
+                                 new MockTupleSource( 5 ),
+                                 new MockObjectSource( 8 ),
+                                 new DefaultBetaConstraints( new BetaNodeFieldConstraint[]{this.constraint},
+                                                             configuration ),
+                                 buildContext );
+
+        this.sink = new MockTupleSink();
+        this.node.addTupleSink( this.sink );
+
+        //        this.ria = new RightInputAdapterNode( 2,
+        //                                              0,
+        //                                              this.node );
+        //        this.ria.attach();
+        //
+        //        this.sink = new MockObjectSink();
+        //        this.ria.addObjectSink( this.sink );
+
+        this.memory = (BetaMemory) this.workingMemory.getNodeMemory( this.node );
+    }
+
+    /**
+     * Test assertion with both Objects and Tuples
+     * 
+     * @throws AssertionException
+     */
+    public void testNotStandard() throws FactException {
+        // assert tuple
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           10 );
+        final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.insert( cheddar );
+
+        final ReteTuple tuple1 = new ReteTuple( f0 );
+
+        this.node.assertTuple( tuple1,
+                               this.context,
+                               this.workingMemory );
+
+        // no matching objects, so should propagate
+        assertLength( 1,
+                      this.sink.getAsserted() );
+
+        assertLength( 0,
+                      this.sink.getRetracted() );
+
+        assertEquals( new ReteTuple( f0 ),
+                      ((Object[]) this.sink.getAsserted().get( 0 ))[0] );
+
+        // assert will match, so propagated tuple should be retracted
+        final Cheese brie = new Cheese( "brie",
+                                        10 );
+        final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.insert( brie );
+
+        this.node.assertObject( f1,
+                                this.context,
+                                this.workingMemory );
+
+        // check no as assertions, but should be one retraction
+        assertLength( 1,
+                      this.sink.getAsserted() );
+
+        assertLength( 1,
+                      this.sink.getRetracted() );
+
+        assertEquals( new ReteTuple( f0 ),
+                      ((Object[]) this.sink.getRetracted().get( 0 ))[0] );
+
+        // assert tuple, will have matches, so no propagation
+        final DefaultFactHandle f2 = (DefaultFactHandle) this.workingMemory.insert( new Cheese( "gouda",
+                                                                                                10 ) );
+        final ReteTuple tuple2 = new ReteTuple( f2 );
+        this.node.assertTuple( tuple2,
+                               this.context,
+                               this.workingMemory );
+
+        // check no propagations 
+        assertLength( 1,
+                      this.sink.getAsserted() );
+
+        assertLength( 1,
+                      this.sink.getRetracted() );
+
+        // check memory sizes
+        assertEquals( 2,
+                      this.memory.getTupleMemory().size() );
+        assertEquals( 1,
+                      this.memory.getFactHandleMemory().size() );
+
+        // When this is retracter both tuples should assert
+        this.node.retractObject( f1,
+                                 this.context,
+                                 this.workingMemory );
+
+        // check propagations 
+        assertLength( 3,
+                      this.sink.getAsserted() );
+
+        assertLength( 1,
+                      this.sink.getRetracted() );
+    }
+
+    /**
+     * Test assertion with both Objects and Tuples
+     * 
+     * @throws AssertionException
+     */
+    public void testNotWithConstraints() throws FactException {
+        this.constraint.isAllowed = false;
+
+        // assert tuple
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           10 );
+        final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.insert( cheddar );
+
+        final ReteTuple tuple1 = new ReteTuple( f0 );
+
+        this.node.assertTuple( tuple1,
+                               this.context,
+                               this.workingMemory );
+
+        // no matching objects, so should propagate
+        assertLength( 1,
+                      this.sink.getAsserted() );
+
+        assertLength( 0,
+                      this.sink.getRetracted() );
+
+        assertEquals( new ReteTuple( f0 ),
+                      ((Object[]) this.sink.getAsserted().get( 0 ))[0] );
+
+        // assert will not match, so activation should stay propagated
+        final Cheese brie = new Cheese( "brie",
+                                        10 );
+        final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.insert( brie );
+
+        this.node.assertObject( f1,
+                                this.context,
+                                this.workingMemory );
+
+        // check no as assertions, but should be one retraction
+        assertLength( 1,
+                      this.sink.getAsserted() );
+
+        assertLength( 0,
+                      this.sink.getRetracted() );
+
+        // assert tuple, will have no matches, so do assert propagation
+        final DefaultFactHandle f2 = (DefaultFactHandle) this.workingMemory.insert( new Cheese( "gouda",
+                                                                                                10 ) );
+        final ReteTuple tuple2 = new ReteTuple( f2 );
+        this.node.assertTuple( tuple2,
+                               this.context,
+                               this.workingMemory );
+
+        // check no as assertions, but should be one retraction
+        assertLength( 2,
+                      this.sink.getAsserted() );
+
+        assertLength( 0,
+                      this.sink.getRetracted() );
+    }
+
+    /**
+     * Tests memory consistency after insert/update/retract calls
+     * 
+     * @throws AssertionException
+     */
+    public void testNotMemoryManagement() throws FactException {
+        try {
+            // assert tuple
+            final Cheese cheddar = new Cheese( "cheddar",
+                                               10 );
+            final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.insert( cheddar );
+            final ReteTuple tuple1 = new ReteTuple( f0 );
+
+            this.node.assertTuple( tuple1,
+                                   this.context,
+                                   this.workingMemory );
+
+            // assert will match, so propagated tuple should be retracted
+            final Cheese brie = new Cheese( "brie",
+                                            10 );
+            final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.insert( brie );
+
+            // Initially, no objects in right memory
+            assertEquals( 0,
+                          this.memory.getFactHandleMemory().size() );
+            this.node.assertObject( f1,
+                                    this.context,
+                                    this.workingMemory );
+
+            // Now, needs to have 1 object in right memory
+            assertEquals( 1,
+                          this.memory.getFactHandleMemory().size() );
+
+            // simulate modify
+            this.node.retractObject( f1,
+                                     this.context,
+                                     this.workingMemory );
+            this.node.assertObject( f1,
+                                    this.context,
+                                    this.workingMemory );
+            // Memory should not change
+            assertEquals( 1,
+                          this.memory.getFactHandleMemory().size() );
+
+            // When this is retracter both tuples should assert
+            this.node.retractObject( f1,
+                                     this.context,
+                                     this.workingMemory );
+            assertEquals( 0,
+                          this.memory.getFactHandleMemory().size() );
+
+            // check memory sizes
+            assertEquals( 1,
+                          this.memory.getTupleMemory().size() );
+
+            // simulate modify
+            this.node.retractTuple( tuple1,
+                                    this.context,
+                                    this.workingMemory );
+            this.node.assertTuple( tuple1,
+                                   this.context,
+                                   this.workingMemory );
+            assertEquals( 1,
+                          this.memory.getTupleMemory().size() );
+            this.node.retractTuple( tuple1,
+                                    this.context,
+                                    this.workingMemory );
+            assertEquals( 0,
+                          this.memory.getTupleMemory().size() );
+        } catch ( final Exception e ) {
+            Assert.fail( "No exception should be raised in this procedure, but got: " + e.toString() );
+        }
+    }
+
+    public void testGetConstraints_ReturnsNullEvenWithEmptyBinder() {
+        final BetaConstraints nullConstraints = EmptyBetaConstraints.getInstance();
+        
+        ReteooRuleBase ruleBase = ( ReteooRuleBase ) RuleBaseFactory.newRuleBase();
+        BuildContext buildContext = new BuildContext( ruleBase, ruleBase.getReteooBuilder().getIdGenerator() );
+        
+        final NotNode notNode = new NotNode( 1,
+                                             this.tupleSource,
+                                             this.objectSource,
+                                             nullConstraints,
+                                             buildContext );
+        final BetaNodeFieldConstraint[] constraints = notNode.getConstraints();
+        assertEquals( 0,
+                      constraints.length );
+    }
+
+    /**
+     * Test just tuple assertions
+     * 
+     * @throws AssertionException
+     */
+    public void testAssertTupleSequentialMode() throws Exception {
+        RuleBaseConfiguration conf = new RuleBaseConfiguration();
+        conf.setSequential( true );
+
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase( conf );
+        
+        this.workingMemory = new ReteooWorkingMemory( 1,
+                                                      ruleBase );
+
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ruleBase.getReteooBuilder().getIdGenerator() );
+        
+        buildContext.setTupleMemoryEnabled( false );
+        buildContext.setObjectTypeNodeMemoryEnabled( false );
+        buildContext.setTerminalNodeMemoryEnabled( false );
+
+        // override setup, so its working in sequential mode
+        this.node = new NotNode( 15,
+                                 this.tupleSource,
+                                 this.objectSource,
+                                 new DefaultBetaConstraints( new BetaNodeFieldConstraint[]{this.constraint},
+                                                             conf ),
+                                 buildContext );
+
+        this.node.addTupleSink( this.sink );
+
+        this.memory = (BetaMemory) this.workingMemory.getNodeMemory( this.node );
+
+        final DefaultFactHandle f0 = new DefaultFactHandle( 0,
+                                                            "cheese" );
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        this.node.assertObject( f0,
+                                this.context,
+                                this.workingMemory );
+
+        // assert tuple
+        this.node.assertTuple( tuple0,
+                               this.context,
+                               this.workingMemory );
+
+        assertEquals( 0,
+                      this.sink.getAsserted().size() );
+
+        assertNull( this.memory.getTupleMemory() );
+
+        assertEquals( 1,
+                      this.memory.getFactHandleMemory().size() );
+
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ObjectSourceTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ObjectSourceTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ObjectSourceTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,91 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.Field;
+
+import org.drools.DroolsTestCase;
+
+public class ObjectSourceTest extends DroolsTestCase {
+
+    public void testObjectSourceConstructor() {
+        final MockObjectSource source = new MockObjectSource( 15 );
+        assertEquals( 15,
+                      source.getId() );
+
+        assertEquals( 0,
+                      source.getAttached() );
+        source.attach();
+        assertEquals( 1,
+                      source.getAttached() );
+    }
+
+    public void testAddObjectSink() throws Exception {
+        final MockObjectSource source = new MockObjectSource( 15 );
+
+        // We need to re-assign this var each time the sink changes references
+        final Field field = ObjectSource.class.getDeclaredField( "sink" );
+        field.setAccessible( true );
+        ObjectSinkPropagator sink = (ObjectSinkPropagator) field.get( source );
+
+        assertSame( EmptyObjectSinkAdapter.getInstance(),
+                    sink );
+
+        final MockObjectSink sink1 = new MockObjectSink();
+        source.addObjectSink( sink1 );
+        sink = (ObjectSinkPropagator) field.get( source );
+        assertSame( SingleObjectSinkAdapter.class,
+                    sink.getClass() );
+        assertEquals( 1,
+                      sink.getSinks().length );
+
+        final MockObjectSink sink2 = new MockObjectSink();
+        source.addObjectSink( sink2 );
+        sink = (ObjectSinkPropagator) field.get( source );
+        assertSame( CompositeObjectSinkAdapter.class,
+                    sink.getClass() );
+        assertEquals( 2,
+                      sink.getSinks().length );
+
+        final MockObjectSink sink3 = new MockObjectSink();
+        source.addObjectSink( sink3 );
+        assertSame( CompositeObjectSinkAdapter.class,
+                    sink.getClass() );
+        assertEquals( 3,
+                      sink.getSinks().length );
+
+        source.removeObjectSink( sink2 );
+        assertSame( CompositeObjectSinkAdapter.class,
+                    sink.getClass() );
+        assertEquals( 2,
+                      sink.getSinks().length );
+
+        source.removeObjectSink( sink1 );
+        sink = (ObjectSinkPropagator) field.get( source );
+        assertSame( SingleObjectSinkAdapter.class,
+                    sink.getClass() );
+        assertEquals( 1,
+                      sink.getSinks().length );
+
+        source.removeObjectSink( sink3 );
+        sink = (ObjectSinkPropagator) field.get( source );
+        assertSame( EmptyObjectSinkAdapter.getInstance(),
+                    sink );
+        assertEquals( 0,
+                      sink.getSinks().length );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ObjectTypeConfTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ObjectTypeConfTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ObjectTypeConfTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,15 @@
+package org.drools.reteoo;
+
+
+import junit.framework.TestCase;
+
+public class ObjectTypeConfTest extends TestCase {
+
+	public void testGetPackageName() {
+		assertEquals("org.drools.reteoo", ClassObjectTypeConf.getPackageName(this.getClass(), null));
+		Package thispkg = this.getClass().getPackage();
+		assertNotNull(thispkg);
+		assertEquals("org.drools.reteoo", ClassObjectTypeConf.getPackageName(this.getClass(), thispkg));
+	}
+	
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ObjectTypeNodeTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ObjectTypeNodeTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ObjectTypeNodeTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,446 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.Cheese;
+import org.drools.DroolsTestCase;
+import org.drools.FactException;
+import org.drools.Person;
+import org.drools.RuleBase;
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuleBaseFactory;
+import org.drools.base.ClassObjectType;
+import org.drools.base.ShadowProxy;
+import org.drools.base.ShadowProxyFactory;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalRuleBase;
+import org.drools.common.PropagationContextImpl;
+import org.drools.reteoo.ReteooBuilder.IdGenerator;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.EntryPoint;
+import org.drools.spi.ObjectType;
+import org.drools.spi.PropagationContext;
+import org.drools.util.FactHashTable;
+import org.drools.util.ObjectHashMap;
+
+public class ObjectTypeNodeTest extends DroolsTestCase {
+    private ReteooRuleBase ruleBase;
+    private BuildContext buildContext;
+    private EntryPointNode entryPoint;
+    
+    protected void setUp() throws Exception {
+        this.ruleBase = ( ReteooRuleBase ) RuleBaseFactory.newRuleBase();
+        this.buildContext = new BuildContext( ruleBase, ((ReteooRuleBase)ruleBase).getReteooBuilder().getIdGenerator() );
+        this.entryPoint = new EntryPointNode( 0,
+                                              this.ruleBase.getRete(),
+                                              buildContext );
+        this.entryPoint.attach();
+    }
+    
+    public void testAttach() throws Exception {
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
+
+        final Rete source = this.ruleBase.getRete();    
+
+        final ObjectType objectType = new ClassObjectType( String.class );
+
+        int id = idGenerator.getNextId();
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( id,
+                                                                  this.entryPoint,
+                                                                  objectType,
+                                                                  buildContext );
+
+        assertEquals( id,
+                      objectTypeNode.getId() );
+
+        Map<ObjectType, ObjectTypeNode> map = source.getObjectTypeNodes( EntryPoint.DEFAULT );
+
+        assertEquals( 0,
+                      map.size() );
+
+        objectTypeNode.attach();
+
+        assertEquals( 1,
+                      map.size() );
+
+        assertSame( objectTypeNode,
+                    map.get( objectType ) );
+    }
+
+    public void testAssertObject() throws Exception {
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
+
+        final ReteooWorkingMemory workingMemory = ( ReteooWorkingMemory ) ruleBase.newStatefulSession();
+
+        final Rete source = ruleBase.getRete();
+
+        final EntryPointNode entryPoint = new EntryPointNode( 0,
+                                                              source, 
+                                                              buildContext );
+        entryPoint.attach();
+
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( idGenerator.getNextId(),
+                                                                  entryPoint,
+                                                                  new ClassObjectType( String.class ),
+                                                                  buildContext );
+
+        final MockObjectSink sink = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink );
+
+        final Object string1 = "cheese";
+
+        final InternalFactHandle handle1 = (InternalFactHandle) workingMemory.insert( string1 );
+
+        // should assert as ObjectType matches
+        objectTypeNode.assertObject( handle1,
+                                     context,
+                                     workingMemory );
+
+        // make sure just string1 was asserted 
+        final List asserted = sink.getAsserted();
+        assertLength( 1,
+                      asserted );
+        assertSame( string1,
+                    workingMemory.getObject( (DefaultFactHandle) ((Object[]) asserted.get( 0 ))[0] ) );
+
+        // check asserted object was added to memory
+        final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( objectTypeNode );
+        assertEquals( 1,
+                      memory.size() );
+        assertTrue( memory.contains( handle1 ) );
+    }
+    
+    public void testAssertObjectSequentialMode() {
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+
+        RuleBaseConfiguration conf = new RuleBaseConfiguration();
+        conf.setSequential( true );
+        final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase( conf );
+        buildContext = new BuildContext( ruleBase, ((ReteooRuleBase)ruleBase).getReteooBuilder().getIdGenerator() );
+        buildContext.setObjectTypeNodeMemoryEnabled( false );
+        
+        final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
+                                                                           ruleBase );
+
+        final Rete source = ruleBase.getRete();
+
+        final EntryPointNode entryPoint = new EntryPointNode( 0,
+                                                              source, 
+                                                              buildContext );
+        entryPoint.attach();
+
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( 1,
+                                                                  entryPoint,
+                                                                  new ClassObjectType( String.class ),
+                                                                  buildContext );
+
+        final MockObjectSink sink = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink );
+
+        final Object string1 = "cheese";
+
+        final InternalFactHandle handle1 = (InternalFactHandle) workingMemory.insert( string1 );
+
+        // should assert as ObjectType matches
+        objectTypeNode.assertObject( handle1,
+                                     context,
+                                     workingMemory );
+
+        // make sure just string1 was asserted 
+        final List asserted = sink.getAsserted();
+        assertLength( 1,
+                      asserted );
+        assertSame( string1,
+                    workingMemory.getObject( (DefaultFactHandle) ((Object[]) asserted.get( 0 ))[0] ) );
+
+        // it's sequential, so check the asserted object was not added to the node memory
+        final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( objectTypeNode );
+        assertEquals( 0,
+                      memory.size() );
+    }
+
+    public void testMemory() {
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();   
+        
+        final ReteooWorkingMemory workingMemory = ( ReteooWorkingMemory ) ruleBase.newStatefulSession();
+
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( idGenerator.getNextId(),
+                                                                  this.entryPoint,
+                                                                  new ClassObjectType( String.class ),
+                                                                  buildContext );
+
+        final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( objectTypeNode );
+
+        assertNotNull( memory );
+    }
+
+    public void testMatches() {
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator(); 
+        final Rete source = new Rete((InternalRuleBase) ruleBase);
+
+        ObjectTypeNode objectTypeNode = new ObjectTypeNode( idGenerator.getNextId(),
+                                                            this.entryPoint,
+                                                            new ClassObjectType( String.class ),
+                                                            buildContext );
+
+        assertFalse( objectTypeNode.matches( new Object() ) );
+        assertFalse( objectTypeNode.matches( new Integer( 5 ) ) );
+        assertTrue( objectTypeNode.matches( "string" ) );
+
+        objectTypeNode = new ObjectTypeNode( idGenerator.getNextId(),
+                                             this.entryPoint,
+                                             new ClassObjectType( Object.class ),
+                                             buildContext );
+
+        assertTrue( objectTypeNode.matches( new Object() ) );
+        assertTrue( objectTypeNode.matches( new Integer( 5 ) ) );
+        assertTrue( objectTypeNode.matches( "string" ) );
+
+    }
+
+    public void testRetractObject() throws Exception {
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();      
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory)ruleBase.newStatefulSession();
+
+        final Rete source = new Rete((InternalRuleBase) ruleBase);
+
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( idGenerator.getNextId(),
+                                                                  this.entryPoint,
+                                                                  new ClassObjectType( String.class ),
+                                                                  buildContext );
+
+        final MockObjectSink sink = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink );
+
+        final Object string1 = "cheese";
+
+        final DefaultFactHandle handle1 = new DefaultFactHandle( 1,
+                                                                 string1 );
+
+        /* should assert as ObjectType matches */
+        objectTypeNode.assertObject( handle1,
+                                     context,
+                                     workingMemory );
+        /* check asserted object was added to memory */
+        final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( objectTypeNode );
+        assertEquals( 1,
+                      memory.size() );
+
+        /* should retract as ObjectType matches */
+        objectTypeNode.retractObject( handle1,
+                                      context,
+                                      workingMemory );
+        /* check asserted object was removed from memory */
+        assertEquals( 0,
+                      memory.size() );
+
+        /* make sure its just the handle1 for string1 that was propagated */
+        final List retracted = sink.getRetracted();
+        assertLength( 1,
+                      retracted );
+        assertSame( handle1,
+                    ((Object[]) retracted.get( 0 ))[0] );
+    }
+
+    public void testUpdateSink() throws FactException {
+        // Tests that when new child is added only the last added child is
+        // updated
+        // When the attachingNewNode flag is set
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase();     
+        final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
+                                                                           (ReteooRuleBase) ruleBase );
+
+        final Rete source = new Rete( (InternalRuleBase)ruleBase);
+
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( 1,
+                                                                  this.entryPoint,
+                                                                  new ClassObjectType( String.class ),
+                                                                  buildContext );
+
+        final MockObjectSink sink1 = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink1 );
+
+        final Object string1 = "cheese";
+
+        final Object string2 = "bread";
+
+        final DefaultFactHandle handle1 = new DefaultFactHandle( 1,
+                                                                 string1 );
+        final DefaultFactHandle handle2 = new DefaultFactHandle( 2,
+                                                                 string2 );
+
+        objectTypeNode.assertObject( handle1,
+                                     context,
+                                     workingMemory );
+
+        objectTypeNode.assertObject( handle2,
+                                     context,
+                                     workingMemory );
+
+        assertEquals( 2,
+                      sink1.getAsserted().size() );
+
+        final MockObjectSink sink2 = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink2 );
+
+        assertEquals( 0,
+                      sink2.getAsserted().size() );
+
+        objectTypeNode.updateSink( sink2,
+                                   null,
+                                   workingMemory );
+
+        assertEquals( 2,
+                      sink2.getAsserted().size() );
+
+        final Object string3 = "water";
+
+        final DefaultFactHandle handle3 = new DefaultFactHandle( 3,
+                                                                 string3 );
+
+        objectTypeNode.assertObject( handle3,
+                                     context,
+                                     workingMemory );
+
+        assertEquals( 3,
+                      sink1.getAsserted().size() );
+
+        assertEquals( 3,
+                      sink2.getAsserted().size() );
+
+    }
+
+    public void testAssertObjectWithShadowEnabled() throws Exception {
+
+        final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
+                                                                           ruleBase );
+
+        final Rete source = ruleBase.getRete();
+
+        final EntryPointNode entryPoint = new EntryPointNode( 0,
+                                                              source, 
+                                                              buildContext );
+        entryPoint.attach();
+
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( 1,
+                                                                  this.entryPoint,
+                                                                  new ClassObjectType( Cheese.class  ),
+                                                                  buildContext );
+
+        final MockObjectSink sink = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink );
+        entryPoint.addObjectSink( objectTypeNode );
+
+        final Object cheese = new Cheese( "muzzarela",
+                                          5 );
+
+        final InternalFactHandle handle1 = (InternalFactHandle) workingMemory.insert( cheese );
+
+        // make sure just string1 was asserted 
+        final List asserted = sink.getAsserted();
+        assertLength( 1,
+                      asserted );
+        assertTrue( ((InternalFactHandle) ((Object[]) asserted.get( 0 ))[0]).getObject() instanceof ShadowProxy );
+        assertEquals( cheese,
+                      ((InternalFactHandle) ((Object[]) asserted.get( 0 ))[0]).getObject() );
+
+        // check asserted object was added to memory
+        final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( objectTypeNode );
+        assertEquals( 1,
+                      memory.size() );
+        assertTrue( memory.contains( handle1 ) );
+    }
+
+    public void testAssertObjectWithShadowEnabledNoDefaultConstr() throws Exception {
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
+        final ReteooWorkingMemory workingMemory = ( ReteooWorkingMemory ) ruleBase.newStatefulSession();
+
+        final Rete source = ruleBase.getRete();
+        
+        final EntryPointNode entryPoint = new EntryPointNode( 0,
+                                                              source, 
+                                                              buildContext );
+        entryPoint.attach();
+
+        final Class shadowClass = ShadowProxyFactory.getProxy( Person.class );
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( idGenerator.getNextId(),
+                                                                  entryPoint,
+                                                                  new ClassObjectType( Person.class ),
+                                                                  buildContext );
+
+        final MockObjectSink sink = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink );
+
+        final Object person = new Person( "bob",
+                                          25 );
+
+        final InternalFactHandle handle1 = (InternalFactHandle) workingMemory.insert( person );
+
+        // should assert as ObjectType matches
+        objectTypeNode.assertObject( handle1,
+                                     context,
+                                     workingMemory );
+
+        // make sure just string1 was asserted 
+        final List asserted = sink.getAsserted();
+        assertLength( 1,
+                      asserted );
+        assertTrue( ((InternalFactHandle) ((Object[]) asserted.get( 0 ))[0]).getObject() instanceof ShadowProxy );
+        assertEquals( ((InternalFactHandle) ((Object[]) asserted.get( 0 ))[0]).getObject(),
+                      person );
+
+        // check asserted object was added to memory
+        final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( objectTypeNode );
+        assertEquals( 1,
+                      memory.size() );
+        assertTrue( memory.contains( handle1 ) );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/OtherwiseTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/OtherwiseTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/OtherwiseTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,159 @@
+package org.drools.reteoo;
+
+import org.drools.Otherwise;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.base.ClassObjectType;
+import org.drools.base.ShadowProxyFactory;
+import org.drools.base.TestBean;
+import org.drools.rule.Pattern;
+import org.drools.rule.Package;
+import org.drools.rule.Rule;
+import org.drools.spi.Consequence;
+import org.drools.spi.KnowledgeHelper;
+
+import junit.framework.TestCase;
+
+/**
+ * This tests the "otherwise" feature.
+ * @author Michael Neale
+ */
+public class OtherwiseTest extends TestCase {
+
+    public void testOneRuleFiringNoOtherwise() throws Exception {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.RETEOO );
+
+        final Package pkg = new Package( "Miss Manners" );
+        final Rule rule1 = getRule( "rule1" );
+        pkg.addRule( rule1 );
+
+        final Rule ruleOtherwise = getOtherwise( "rule2" );
+        pkg.addRule( ruleOtherwise );
+
+        ruleBase.addPackage( pkg );
+
+        final WorkingMemory workingMemory = ruleBase.newStatefulSession();
+        workingMemory.insert( new TestBean() );
+        workingMemory.fireAllRules();
+
+        assertTrue( ((MockConsequence) rule1.getConsequence()).fired );
+        assertFalse( ((MockConsequence) ruleOtherwise.getConsequence()).fired );
+
+    }
+
+    public void testTwoRulesFiringNoOtherwise() throws Exception {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.RETEOO );
+
+        final Package pkg = new Package( "Miss Manners" );
+        final Rule rule1 = getRule( "rule1" );
+        pkg.addRule( rule1 );
+        final Rule rule2 = getRule( "rule2" );
+        pkg.addRule( rule2 );
+
+        final Rule ruleOtherwise = getOtherwise( "ruleOtherwise" );
+        pkg.addRule( ruleOtherwise );
+
+        ruleBase.addPackage( pkg );
+
+        final WorkingMemory workingMemory = ruleBase.newStatefulSession();
+        workingMemory.insert( new TestBean() );
+        workingMemory.fireAllRules();
+
+        assertFalse( ((MockConsequence) ruleOtherwise.getConsequence()).fired );
+        assertTrue( ((MockConsequence) rule1.getConsequence()).fired );
+        assertTrue( ((MockConsequence) rule2.getConsequence()).fired );
+
+    }
+
+    /**
+     * @TODO: this is a future to be implemented in the future 
+     * @throws Exception
+     */
+    public void FIXME_testOtherwiseFiringWithOneRule() throws Exception {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.RETEOO );
+
+        final Package pkg = new Package( "Miss Manners" );
+        final Rule rule1 = getRule( "rule1" );
+        pkg.addRule( rule1 );
+
+        final Rule ruleOtherwise = getOtherwise( "rule2" );
+        pkg.addRule( ruleOtherwise );
+
+        ruleBase.addPackage( pkg );
+
+        final WorkingMemory workingMemory = ruleBase.newStatefulSession();
+
+        workingMemory.fireAllRules();
+
+        assertFalse( ((MockConsequence) rule1.getConsequence()).fired );
+        assertTrue( ((MockConsequence) ruleOtherwise.getConsequence()).fired );
+
+    }
+
+    /**
+     * @TODO: this is a future to be implemented in the future 
+     * @throws Exception
+     */
+    public void FIXME_testOtherwiseFiringMultipleRules() throws Exception {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.RETEOO );
+
+        final Package pkg = new Package( "Miss Manners" );
+        final Rule rule1 = getRule( "rule1" );
+        pkg.addRule( rule1 );
+        final Rule rule2 = getRule( "rule2" );
+        pkg.addRule( rule2 );
+
+        final Rule ruleOtherwise1 = getOtherwise( "other1" );
+        pkg.addRule( ruleOtherwise1 );
+        final Rule ruleOtherwise2 = getOtherwise( "other2" );
+        pkg.addRule( ruleOtherwise2 );
+
+        ruleBase.addPackage( pkg );
+
+        final WorkingMemory workingMemory = ruleBase.newStatefulSession();
+
+        workingMemory.fireAllRules();
+
+        assertFalse( ((MockConsequence) rule1.getConsequence()).fired );
+        assertFalse( ((MockConsequence) rule2.getConsequence()).fired );
+        assertTrue( ((MockConsequence) ruleOtherwise1.getConsequence()).fired );
+        assertTrue( ((MockConsequence) ruleOtherwise2.getConsequence()).fired );
+
+    }
+
+    private Rule getOtherwise(final String name) {
+        final Rule rule = new Rule( name );
+        final Pattern pat = new Pattern( 0,
+                                       new ClassObjectType( Otherwise.class) );
+        rule.addPattern( pat );
+        rule.setConsequence( new MockConsequence() );
+        return rule;
+    }
+
+    private Rule getRule(final String name) {
+        final Rule rule = new Rule( name );
+
+        final Pattern pat = new Pattern( 0,
+                                       new ClassObjectType( TestBean.class ) );
+
+        rule.addPattern( pat );
+        rule.setConsequence( new MockConsequence() );
+
+        return rule;
+    }
+
+    static class MockConsequence
+        implements
+        Consequence {
+
+        public boolean fired = false;
+
+        public void evaluate(final KnowledgeHelper knowledgeHelper,
+                             final WorkingMemory workingMemory) throws Exception {
+            this.fired = true;
+        }
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/PropertyChangeListenerTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/PropertyChangeListenerTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/PropertyChangeListenerTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,79 @@
+package org.drools.reteoo;
+
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+
+import junit.framework.TestCase;
+
+import org.drools.RuleBaseFactory;
+import org.drools.base.ClassObjectType;
+import org.drools.reteoo.builder.BuildContext;
+
+public class PropertyChangeListenerTest extends TestCase {
+    private ReteooRuleBase ruleBase;
+    private BuildContext buildContext;
+    private EntryPointNode entryPoint;
+    
+    protected void setUp() throws Exception {
+        this.ruleBase = ( ReteooRuleBase ) RuleBaseFactory.newRuleBase();
+        this.buildContext = new BuildContext( ruleBase, ((ReteooRuleBase)ruleBase).getReteooBuilder().getIdGenerator() );
+        this.entryPoint = new EntryPointNode( 0,
+                                              this.ruleBase.getRete(),
+                                              buildContext );
+        this.entryPoint.attach();
+    }
+    
+    public void test1() {
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( 1,
+                                                                  this.entryPoint,
+                                                                  new ClassObjectType( State.class ),
+                                                                  buildContext );
+
+        objectTypeNode.attach();
+
+        final MockObjectSink sink = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink );
+
+        final State a = new State( "go" );
+        workingMemory.insert( a,
+                                    true );
+
+        assertEquals( 1,
+                      sink.getAsserted().size() );
+
+        a.setState( "stop" );
+
+    }
+
+    public static class State {
+        private final PropertyChangeSupport changes = new PropertyChangeSupport( this );
+
+        private String                      state;
+
+        public State(final String state) {
+            this.state = state;
+        }
+
+        public String getState() {
+            return this.state;
+        }
+
+        public void setState(final String newState) {
+            final String oldState = this.state;
+            this.state = newState;
+            this.changes.firePropertyChange( "state",
+                                             oldState,
+                                             newState );
+        }
+
+        public void addPropertyChangeListener(final PropertyChangeListener l) {
+            this.changes.addPropertyChangeListener( l );
+        }
+
+        public void removePropertyChangeListener(final PropertyChangeListener l) {
+            this.changes.removePropertyChangeListener( l );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/QueryTerminalNodeTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/QueryTerminalNodeTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/QueryTerminalNodeTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,249 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.Field;
+import java.util.Iterator;
+import java.util.Map;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.drools.FactHandle;
+import org.drools.QueryResult;
+import org.drools.QueryResults;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.base.ClassFieldExtractor;
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.ClassObjectType;
+import org.drools.base.DroolsQuery;
+import org.drools.base.FieldFactory;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.EqualityEvaluatorsDefinition;
+import org.drools.base.evaluators.Operator;
+import org.drools.common.EmptyBetaConstraints;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.LiteralConstraint;
+import org.drools.rule.Query;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldValue;
+
+public class QueryTerminalNodeTest extends TestCase {
+    private ReteooRuleBase   ruleBase;
+    private BuildContext     buildContext;
+    private EntryPointNode   entryPoint;
+
+    ClassFieldExtractorCache cache = ClassFieldExtractorCache.getInstance();
+    private EqualityEvaluatorsDefinition equals = new EqualityEvaluatorsDefinition();
+
+    protected void setUp() throws Exception {
+        this.ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        this.buildContext = new BuildContext( ruleBase,
+                                              ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator() );
+        this.entryPoint = new EntryPointNode( 0,
+                                              this.ruleBase.getRete(),
+                                              buildContext );
+        this.entryPoint.attach();
+    }
+
+    public void testQueryTerminalNode() {
+        final ClassObjectType queryObjectType = new ClassObjectType( DroolsQuery.class );
+        final ObjectTypeNode queryObjectTypeNode = new ObjectTypeNode( this.buildContext.getNextId(),
+                                                                       this.entryPoint,
+                                                                       queryObjectType,
+                                                                       buildContext );
+        queryObjectTypeNode.attach();
+
+        ClassFieldExtractor extractor = cache.getExtractor( DroolsQuery.class,
+                                                            "name",
+                                                            DroolsQuery.class.getClassLoader() );
+
+        FieldValue field = FieldFactory.getFieldValue( "query-1" );
+
+        final Evaluator evaluator = equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL );
+        LiteralConstraint constraint = new LiteralConstraint( extractor,
+                                                              evaluator,
+                                                              field );
+
+        AlphaNode alphaNode = new AlphaNode( this.buildContext.getNextId(),
+                                             constraint,
+                                             queryObjectTypeNode,
+                                             buildContext );
+        alphaNode.attach();
+
+        final LeftInputAdapterNode liaNode = new LeftInputAdapterNode( this.buildContext.getNextId(),
+                                                                       alphaNode,
+                                                                       this.buildContext );
+        liaNode.attach();
+
+        final ClassObjectType cheeseObjectType = new ClassObjectType( Cheese.class );
+        final ObjectTypeNode cheeseObjectTypeNode = new ObjectTypeNode( this.buildContext.getNextId(),
+                                                                        this.entryPoint,
+                                                                        cheeseObjectType,
+                                                                        buildContext );
+        cheeseObjectTypeNode.attach();
+
+        extractor = cache.getExtractor( Cheese.class,
+                                        "type",
+                                        getClass().getClassLoader() );
+
+        field = FieldFactory.getFieldValue( "stilton" );
+
+        constraint = new LiteralConstraint( extractor,
+                                            evaluator,
+                                            field );
+
+        alphaNode = new AlphaNode( this.buildContext.getNextId(),
+                                   constraint,
+                                   cheeseObjectTypeNode,
+                                   buildContext );
+        alphaNode.attach();
+
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ruleBase.getReteooBuilder().getIdGenerator() );
+        buildContext.setTupleMemoryEnabled( false );
+
+        final JoinNode joinNode = new JoinNode( this.buildContext.getNextId(),
+                                                liaNode,
+                                                alphaNode,
+                                                EmptyBetaConstraints.getInstance(),
+                                                buildContext );
+        joinNode.attach();
+
+        final Query query = new Query( "query-1" );
+
+        final QueryTerminalNode queryNode = new QueryTerminalNode( this.buildContext.getNextId(),
+                                                                   joinNode,
+                                                                   query,
+                                                                   query.getLhs() );
+
+        queryNode.attach();
+
+        final org.drools.rule.Package pkg = new org.drools.rule.Package( "com.drools.test" );
+        pkg.addRule( query );
+
+        try {
+            final Field pkgField = ruleBase.getClass().getSuperclass().getDeclaredField( "pkgs" );
+            pkgField.setAccessible( true );
+            final Map pkgs = (Map) pkgField.get( ruleBase );
+            pkgs.put( pkg.getName(),
+                      pkg );
+        } catch ( final Exception e ) {
+            Assert.fail( "Should not throw any exception: " + e.getMessage() );
+        }
+
+        final WorkingMemory workingMemory = ruleBase.newStatefulSession();
+        QueryResults results = workingMemory.getQueryResults( "query-1" );
+
+        assertEquals( 0,
+                      results.size() );
+
+        final Cheese stilton1 = new Cheese( "stilton",
+                                            100 );
+        final FactHandle handle1 = workingMemory.insert( stilton1 );
+
+        results = workingMemory.getQueryResults( "query-1" );
+
+        assertEquals( 1,
+                      results.size() );
+
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           55 );
+        workingMemory.insert( cheddar );
+
+        results = workingMemory.getQueryResults( "query-1" );
+
+        assertEquals( 1,
+                      results.size() );
+
+        final Cheese stilton2 = new Cheese( "stilton",
+                                            5 );
+
+        final FactHandle handle2 = workingMemory.insert( stilton2 );
+
+        results = workingMemory.getQueryResults( "query-1" );
+
+        assertEquals( 2,
+                      results.size() );
+
+        QueryResult result = results.get( 0 );
+        assertEquals( 1,
+                      result.size() );
+        assertEquals( stilton2,
+                      result.get( 0 ) );
+
+        result = results.get( 1 );
+        assertEquals( 1,
+                      result.size() );
+        assertEquals( stilton1,
+                      result.get( 0 ) );
+
+        int i = 0;
+        for ( final Iterator it = results.iterator(); it.hasNext(); ) {
+            result = (QueryResult) it.next();
+            assertEquals( 1,
+                          result.size() );
+            if ( i == 1 ) {
+                assertSame( stilton1,
+                            result.get( 0 ) );
+            } else {
+                assertSame( stilton2,
+                            result.get( 0 ) );
+            }
+            i++;
+        }
+
+        workingMemory.retract( handle1 );
+        results = workingMemory.getQueryResults( "query-1" );
+
+        assertEquals( 1,
+                      results.size() );
+
+        workingMemory.retract( handle2 );
+        results = workingMemory.getQueryResults( "query-1" );
+
+        assertEquals( 0,
+                      results.size() );
+
+    }
+
+    public class Cheese {
+        private String type;
+        private int    price;
+
+        public Cheese(final String type,
+                      final int price) {
+            super();
+            this.type = type;
+            this.price = price;
+        }
+
+        public int getPrice() {
+            return this.price;
+        }
+
+        public String getType() {
+            return this.type;
+        }
+
+        public String toString() {
+            return "[Cheese type='" + this.type + "' price='" + this.price + "']";
+        }
+
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ReteTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ReteTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ReteTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,450 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.drools.Cheese;
+import org.drools.DroolsTestCase;
+import org.drools.FactException;
+import org.drools.FactHandle;
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuleBaseFactory;
+import org.drools.base.ClassObjectType;
+import org.drools.base.ShadowProxy;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.reteoo.ReteooBuilder.IdGenerator;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.EntryPoint;
+import org.drools.spi.PropagationContext;
+
+/**
+ * @author mproctor
+ *
+ */
+public class ReteTest extends DroolsTestCase {
+    private ReteooRuleBase ruleBase;
+    private BuildContext   buildContext;
+    private EntryPointNode entryPoint;
+
+    protected void setUp() throws Exception {
+        this.ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        this.buildContext = new BuildContext( ruleBase,
+                                              ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator() );
+        this.entryPoint = new EntryPointNode( 0,
+                                              this.ruleBase.getRete(),
+                                              buildContext );
+        this.entryPoint.attach();
+
+    }
+
+    /**
+     * Tests ObjectTypeNodes are correctly added to the Rete object
+     * 
+     * @throws Exception
+     */
+    public void testObjectTypeNodes() throws Exception {
+        final Rete rete = ruleBase.getRete();
+
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( 1,
+                                                                  this.entryPoint,
+                                                                  new ClassObjectType( Object.class ),
+                                                                  buildContext );
+        objectTypeNode.attach();
+
+        final ObjectTypeNode stringTypeNode = new ObjectTypeNode( 2,
+                                                                  this.entryPoint,
+                                                                  new ClassObjectType( String.class ),
+                                                                  buildContext );
+        stringTypeNode.attach();
+
+        final List<ObjectTypeNode> list = rete.getObjectTypeNodes();
+
+        // Check the ObjectTypeNodes are correctly added to Rete
+        assertEquals( 2,
+                      list.size() );
+
+        assertTrue( list.contains( objectTypeNode ) );
+        assertTrue( list.contains( stringTypeNode ) );
+    }
+
+    /**
+     * Tests that interfaces and parent classes for an asserted  class are  cached, for  quick future iterations
+     * 
+     * @throws FactException
+     */
+    public void testCache() throws FactException {
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) this.ruleBase.newStatefulSession();
+
+        // Create a Rete network with ObjectTypeNodes for List, Collection and ArrayList
+        final Rete rete = ruleBase.getRete();
+        ObjectTypeNode objectTypeNode = new ObjectTypeNode( 1,
+                                                            this.entryPoint,
+                                                            new ClassObjectType( List.class ),
+                                                            buildContext );
+        objectTypeNode.attach();
+        MockObjectSink sink = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink );
+
+        objectTypeNode = new ObjectTypeNode( 1,
+                                             this.entryPoint,
+                                             new ClassObjectType( Collection.class ),
+                                             buildContext );
+        objectTypeNode.attach();
+        sink = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink );
+
+        objectTypeNode = new ObjectTypeNode( 1,
+                                             this.entryPoint,
+                                             new ClassObjectType( ArrayList.class ),
+                                             buildContext );
+        objectTypeNode.attach();
+        sink = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink );
+
+        // ArrayList matches all three ObjectTypeNodes
+        final DefaultFactHandle h1 = new DefaultFactHandle( 1,
+                                                            new ArrayList() );
+        rete.assertObject( h1,
+                           new PropagationContextImpl( 0,
+                                                       PropagationContext.ASSERTION,
+                                                       null,
+                                                       null ),
+                           workingMemory );
+
+        // LinkedList matches two ObjectTypeNodes        
+        h1.setObject( new LinkedList() );
+        rete.assertObject( h1,
+                           new PropagationContextImpl( 0,
+                                                       PropagationContext.ASSERTION,
+                                                       null,
+                                                       null ),
+                           workingMemory );
+
+        final Map map = workingMemory.getObjectTypeConfMap( EntryPoint.DEFAULT );
+        ClassObjectTypeConf conf = (ClassObjectTypeConf) map.get( ArrayList.class );
+        assertLength( 3,
+                      conf.getObjectTypeNodes() );
+
+        conf = (ClassObjectTypeConf) map.get( LinkedList.class );
+        assertLength( 3,
+                      conf.getObjectTypeNodes() );
+
+    }
+
+    /**
+     * Test asserts correctly propagate
+     * 
+     * @throws Exception
+     */
+    public void testAssertObject() throws Exception {
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) this.ruleBase.newStatefulSession();
+
+        // Create a Rete network with ObjectTypeNodes for List, Collection and ArrayList
+        final Rete rete = ruleBase.getRete();
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( 1,
+                                                                  this.entryPoint,
+                                                                  new ClassObjectType( List.class ),
+                                                                  buildContext );
+        objectTypeNode.attach();
+        final MockObjectSink sink1 = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink1 );
+
+        // There are no String ObjectTypeNodes, make sure its not propagated
+
+        final String string = "String";
+        final DefaultFactHandle h1 = new DefaultFactHandle( 1,
+                                                            string );
+
+        rete.assertObject( h1,
+                           new PropagationContextImpl( 0,
+                                                       PropagationContext.ASSERTION,
+                                                       null,
+                                                       null ),
+                           workingMemory );
+
+        assertLength( 0,
+                      sink1.getAsserted() );
+
+        // There is a List ObjectTypeNode, make sure it was propagated
+        final List list = new ArrayList();
+        final DefaultFactHandle h2 = new DefaultFactHandle( 1,
+                                                            list );
+
+        rete.assertObject( h2,
+                           new PropagationContextImpl( 0,
+                                                       PropagationContext.ASSERTION,
+                                                       null,
+                                                       null ),
+                           workingMemory );
+
+        final List asserted = sink1.getAsserted();
+        assertLength( 1,
+                      asserted );
+
+        final Object[] results = (Object[]) asserted.get( 0 );
+        assertSame( list,
+                    unwrapShadow( ((DefaultFactHandle) results[0]).getObject() ) );
+    }
+
+    public void testAssertObjectWithNoMatchingObjectTypeNode() {
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) this.ruleBase.newStatefulSession();
+
+        final Rete rete = ruleBase.getRete();
+        assertEquals( 0,
+                      rete.getObjectTypeNodes().size() );
+
+        List list = new ArrayList();
+
+        workingMemory.insert( list );
+
+        assertEquals( 2,
+                      rete.getObjectTypeNodes().size() );
+    }
+
+    public void testHierarchy() {
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) this.ruleBase.newStatefulSession();
+
+        final Rete rete = ruleBase.getRete();
+        final IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
+
+        // Attach a List ObjectTypeNode
+        final ObjectTypeNode listOtn = new ObjectTypeNode( idGenerator.getNextId(),
+                                                           this.entryPoint,
+                                                           new ClassObjectType( List.class ),
+                                                           buildContext );
+        listOtn.attach();
+
+        // Will automatically create an ArrayList ObjectTypeNode
+        FactHandle handle = workingMemory.insert( new ArrayList() );
+
+        // Check we have three ObjectTypeNodes, List, ArrayList and InitialFactImpl
+        assertEquals( 3,
+                      rete.getObjectTypeNodes().size() );
+
+        // double check that the Listreference is the same as the one we created, i.e. engine should try and recreate it
+        assertSame( listOtn,
+                    rete.getObjectTypeNodes( EntryPoint.DEFAULT ).get( new ClassObjectType( List.class ) ) );
+
+        // ArrayConf should match two ObjectTypenodes for List and ArrayList
+        Map memory = workingMemory.getObjectTypeConfMap( EntryPoint.DEFAULT );
+        ObjectTypeConf arrayConf = (ObjectTypeConf) memory.get( ArrayList.class );
+        final ObjectTypeNode arrayOtn = arrayConf.getConcreteObjectTypeNode();
+        assertEquals( 2,
+                      arrayConf.getObjectTypeNodes().length );
+
+        // Check it contains List and ArrayList
+        List nodes = Arrays.asList( arrayConf.getObjectTypeNodes() );
+        assertEquals( 2,
+                      nodes.size() );
+        assertTrue( nodes.contains( arrayOtn ) );
+        assertTrue( nodes.contains( listOtn ) );
+
+        // Nodes are there, retract the fact so we can check both nodes are populated
+        workingMemory.retract( handle );
+
+        // Add MockSinks so we can track assertions
+        final MockObjectSink listSink = new MockObjectSink();
+        listOtn.addObjectSink( listSink );
+
+        final MockObjectSink arraySink = new MockObjectSink();
+        listOtn.addObjectSink( arraySink );
+
+        workingMemory.insert( new ArrayList() );
+        assertEquals( 1,
+                      listSink.getAsserted().size() );
+        assertEquals( 1,
+                      arraySink.getAsserted().size() );
+
+        // Add a Collection ObjectTypeNode, so that we can check that the data from ArrayList is sent to it
+        final ObjectTypeNode collectionOtn = new ObjectTypeNode( idGenerator.getNextId(),
+                                                                 this.entryPoint,
+                                                                 new ClassObjectType( Collection.class ),
+                                                                 buildContext );
+        final MockObjectSink collectionSink = new MockObjectSink();
+        collectionOtn.addObjectSink( collectionSink );
+        collectionOtn.attach( new InternalWorkingMemory[]{workingMemory} );
+
+        assertEquals( 1,
+                      collectionSink.getAsserted().size() );
+
+        // check that ArrayListConf was updated with the new ObjectTypeNode
+        nodes = Arrays.asList( arrayConf.getObjectTypeNodes() );
+        assertEquals( 3,
+                      nodes.size() );
+        assertTrue( nodes.contains( arrayOtn ) );
+        assertTrue( nodes.contains( listOtn ) );
+        assertTrue( nodes.contains( collectionOtn ) );
+    }
+
+    /**
+     * All objects retracted from a RootNode must be propagated to all children
+     * ObjectTypeNodes.
+     */
+    public void testRetractObject() throws Exception {
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) this.ruleBase.newStatefulSession();
+
+        // Create a Rete network with ObjectTypeNodes for List, Collection and ArrayList
+        final Rete rete = ruleBase.getRete();
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( 1,
+                                                                  this.entryPoint,
+                                                                  new ClassObjectType( List.class ),
+                                                                  buildContext );
+        objectTypeNode.attach();
+        final MockObjectSink sink1 = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink1 );
+
+        // There are no String ObjectTypeNodes, make sure its not propagated
+        final String string = "String";
+        final DefaultFactHandle h1 = new DefaultFactHandle( 1,
+                                                            string );
+
+        rete.assertObject( h1,
+                           new PropagationContextImpl( 0,
+                                                       PropagationContext.ASSERTION,
+                                                       null,
+                                                       null ),
+                           workingMemory );
+        assertLength( 0,
+                      sink1.getAsserted() );
+        assertLength( 0,
+                      sink1.getRetracted() );
+
+        // There is a List ObjectTypeNode, make sure it was propagated
+        final List list = new ArrayList();
+        final DefaultFactHandle h2 = new DefaultFactHandle( 1,
+                                                            list );
+
+        // need  to assert first, to force it to build  up the cache
+        rete.assertObject( h2,
+                           new PropagationContextImpl( 0,
+                                                       PropagationContext.ASSERTION,
+                                                       null,
+                                                       null ),
+                           workingMemory );
+
+        rete.retractObject( h2,
+                            new PropagationContextImpl( 0,
+                                                        PropagationContext.ASSERTION,
+                                                        null,
+                                                        null ),
+                            workingMemory );
+
+        final List retracted = sink1.getRetracted();
+        assertLength( 1,
+                      retracted );
+
+        final Object[] results = (Object[]) retracted.get( 0 );
+        assertSame( list,
+                    unwrapShadow( ((DefaultFactHandle) results[0]).getObject() ) );
+    }
+
+    public void testIsShadowed() {
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) this.ruleBase.newStatefulSession();
+
+        // Create a Rete network with ObjectTypeNodes for List, Collection and ArrayList
+        final Rete rete = ruleBase.getRete();
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( 1,
+                                                                  this.entryPoint,
+                                                                  new ClassObjectType( Cheese.class ),
+                                                                  buildContext );
+        objectTypeNode.attach();
+        final MockObjectSink sink1 = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink1 );
+
+        // There are no String ObjectTypeNodes, make sure its not propagated
+
+        final Cheese cheese = new Cheese( "brie",
+                                          15 );
+        final DefaultFactHandle h1 = new DefaultFactHandle( 1,
+                                                            cheese );
+
+        rete.assertObject( h1,
+                           new PropagationContextImpl( 0,
+                                                       PropagationContext.ASSERTION,
+                                                       null,
+                                                       null ),
+                           workingMemory );
+
+        assertTrue( h1.isShadowFact() );
+
+        final Object[] results = (Object[]) sink1.getAsserted().get( 0 );
+        assertTrue( ((DefaultFactHandle) results[0]).getObject() instanceof ShadowProxy );
+    }
+
+    public void testNotShadowed() {
+
+        Properties properties = new Properties();
+        properties.setProperty( "drools.shadowProxyExcludes",
+                                "org.drools.Cheese" );
+        RuleBaseConfiguration conf = new RuleBaseConfiguration( properties );
+        final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase( conf );
+        buildContext = new BuildContext( ruleBase,
+                                         ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator() );
+        final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
+                                                                           ruleBase );
+
+        // Create a Rete network with ObjectTypeNodes for List, Collection and ArrayList
+        final Rete rete = ruleBase.getRete();
+        final EntryPointNode entryPoint = new EntryPointNode( 0,
+                                                              rete,
+                                                              buildContext );
+        entryPoint.attach();
+        
+        final ObjectTypeNode objectTypeNode = new ObjectTypeNode( 1,
+                                                                  entryPoint,
+                                                                  new ClassObjectType( Cheese.class ),
+                                                                  buildContext );
+        objectTypeNode.attach();
+        final MockObjectSink sink1 = new MockObjectSink();
+        objectTypeNode.addObjectSink( sink1 );
+
+        // There are no String ObjectTypeNodes, make sure its not propagated
+
+        final Cheese cheese = new Cheese( "brie",
+                                          15 );
+        final DefaultFactHandle h1 = new DefaultFactHandle( 1,
+                                                            cheese );
+
+        rete.assertObject( h1,
+                           new PropagationContextImpl( 0,
+                                                       PropagationContext.ASSERTION,
+                                                       null,
+                                                       null ),
+                           workingMemory );
+
+        assertFalse( h1.isShadowFact() );
+        final Object[] results = (Object[]) sink1.getAsserted().get( 0 );
+        assertFalse( ((DefaultFactHandle) results[0]).getObject() instanceof ShadowProxy );
+    }
+
+    private Object unwrapShadow(Object object) {
+        if ( object instanceof ShadowProxy ) {
+            return ((ShadowProxy) object).getShadowedObject();
+        } else {
+            return object;
+        }
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ReteooBuilderTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ReteooBuilderTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ReteooBuilderTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,89 @@
+package org.drools.reteoo;
+
+import org.drools.RuleBaseConfiguration;
+import org.drools.WorkingMemory;
+import org.drools.base.SalienceInteger;
+import org.drools.rule.Rule;
+import org.drools.spi.Consequence;
+import org.drools.spi.KnowledgeHelper;
+
+import junit.framework.TestCase;
+
+public class ReteooBuilderTest extends TestCase {
+    
+    public void testOrder() {
+        //ReteooBuilder
+        RuleBaseConfiguration conf = new RuleBaseConfiguration();
+        conf.setSequential( true );
+        ReteooRuleBase ruleBase = new ReteooRuleBase( conf );
+        ReteooBuilder builder = new ReteooBuilder( ruleBase );
+        
+        
+        final Consequence consequence = new Consequence() {
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory workingMemory) throws Exception {
+                System.out.println( "Consequence!" );
+            }
+        };        
+        
+        Rule rule0 = new Rule( "rule0" );
+        rule0.setAgendaGroup( "group 0" );
+        rule0.setConsequence( consequence );
+        builder.addRule( rule0 );
+        
+        Rule rule1 = new Rule( "rule1" );
+        rule1.setAgendaGroup( "group 0" );
+        rule1.setConsequence( consequence );
+        builder.addRule( rule1 );
+        
+        Rule rule2 = new Rule( "rule2" );
+        rule2.setAgendaGroup( "group 1" );
+        rule2.setConsequence( consequence );
+        builder.addRule( rule2 );
+        
+        Rule rule3 = new Rule( "rule3" );
+        rule3.setAgendaGroup( "group 0" );
+        rule3.setConsequence( consequence );
+        builder.addRule( rule3 );
+
+        Rule rule4 = new Rule( "rule4" );
+        rule4.setAgendaGroup( "group 2" );  
+        rule4.setConsequence( consequence );
+        builder.addRule( rule4 );
+        
+        Rule rule5 = new Rule( "rule5" );
+        rule5.setAgendaGroup( "group 1" );        
+        rule5.setConsequence( consequence );
+        builder.addRule( rule5 );
+        
+        Rule rule6 = new Rule( "rule6" );
+        rule6.setSalience( new SalienceInteger( 5 ) );
+        rule6.setAgendaGroup( "group 2" );  
+        rule6.setConsequence( consequence );
+        builder.addRule( rule6 );        
+
+        Rule rule7 = new Rule( "rule7" );
+        rule7.setAgendaGroup( "group 0" );
+        rule7.setConsequence( consequence );
+        builder.addRule( rule7 );        
+
+        Rule rule8 = new Rule( "rule8" );
+        rule8.setSalience( new SalienceInteger( 10 ) );
+        rule8.setAgendaGroup( "group 2" );  
+        rule8.setConsequence( consequence );
+        builder.addRule( rule8 );        
+        
+        builder.order();
+        
+        assertEquals( 0, ((RuleTerminalNode) builder.getTerminalNodes( rule0 )[0]).getSequence() );
+        assertEquals( 1, ((RuleTerminalNode) builder.getTerminalNodes( rule1 )[0]).getSequence() );
+        assertEquals( 0, ((RuleTerminalNode) builder.getTerminalNodes( rule2 )[0]).getSequence() ); 
+        assertEquals( 2, ((RuleTerminalNode) builder.getTerminalNodes( rule3 )[0]).getSequence() );
+        assertEquals( 2, ((RuleTerminalNode) builder.getTerminalNodes( rule4 )[0]).getSequence() );
+        assertEquals( 1, ((RuleTerminalNode) builder.getTerminalNodes( rule5 )[0]).getSequence() );        
+        assertEquals( 1, ((RuleTerminalNode) builder.getTerminalNodes( rule6 )[0]).getSequence() );    
+        assertEquals( 3, ((RuleTerminalNode) builder.getTerminalNodes( rule7 )[0]).getSequence() );    
+        assertEquals( 0, ((RuleTerminalNode) builder.getTerminalNodes( rule8 )[0]).getSequence() );            
+                                
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ReteooRuleBaseTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ReteooRuleBaseTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ReteooRuleBaseTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,170 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.DroolsTestCase;
+import org.drools.RuleBaseFactory;
+import org.drools.StatefulSession;
+import org.drools.WorkingMemory;
+
+public class ReteooRuleBaseTest extends DroolsTestCase {
+    ReteooRuleBase ruleBase;
+
+    StatefulSession  wm1;
+    StatefulSession  wm2;
+    StatefulSession  wm3;
+    StatefulSession  wm4;
+
+    public void setUp() {
+        this.ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+
+        this.wm1 = this.ruleBase.newStatefulSession();
+        this.wm2 = this.ruleBase.newStatefulSession();
+        this.wm3 = this.ruleBase.newStatefulSession();
+        this.wm4 = this.ruleBase.newStatefulSession();
+    }
+
+    public void testKeepReference() throws Exception {
+        /* Make sure the RuleBase is referencing all 4 Working Memories */
+        assertLength( 4,
+                      this.ruleBase.getStatefulSessions() );
+        assertContains( this.wm1, this.ruleBase.getStatefulSessions() );
+        assertContains( this.wm2, this.ruleBase.getStatefulSessions() );
+        assertContains( this.wm3, this.ruleBase.getStatefulSessions() );
+        assertContains( this.wm4, this.ruleBase.getStatefulSessions() );
+    }
+    
+    public void testDispose() throws Exception {
+        /*
+         * Now lets test the dispose method on the WorkingMemory itself. dispose
+         * doesn't need GC
+         */
+        this.wm3.dispose();
+
+        /* Check only wm3 was removed */
+        assertLength( 3,
+                      this.ruleBase.getStatefulSessions() );
+        assertNotContains( this.wm3, this.ruleBase.getStatefulSessions() );
+    }
+
+    public void testNoKeepReference() throws Exception {
+        final WorkingMemory wm5 = this.ruleBase.newStatefulSession( false );
+        final WorkingMemory wm6 = this.ruleBase.newStatefulSession( false );
+        assertLength( 4,
+                      this.ruleBase.getStatefulSessions() );
+        assertNotContains( wm5, this.ruleBase.getStatefulSessions() );
+        assertNotContains( wm6, this.ruleBase.getStatefulSessions() );
+    }
+
+    public void testAddPackage() throws Exception {
+        final org.drools.rule.Package pkg1 = new org.drools.rule.Package( "org.droos.test" );
+        pkg1.addGlobal( "global1",
+                        Object.class );
+        pkg1.addGlobal( "global2",
+                        Object.class );
+
+        final org.drools.rule.Package pkg2 = new org.drools.rule.Package( "org.droos.test" );
+        pkg2.addGlobal( "global1",
+                        Object.class );
+        pkg2.addGlobal( "global3",
+                        Object.class );
+
+        final org.drools.rule.Package pkg3 = new org.drools.rule.Package( "org.droos.test2" );
+        pkg3.addGlobal( "global3",
+                        Object.class );
+        pkg3.addGlobal( "global4",
+                        Object.class );
+
+        this.ruleBase.addPackage( pkg1 );
+        // one package
+        assertLength( 1,
+                      this.ruleBase.getPackages() );
+        // two globals
+        assertLength( 2,
+                      this.ruleBase.getGlobals().values() );
+        // two globals in the package also
+        assertLength( 2,
+                      this.ruleBase.getPackages()[0].getGlobals().values() );
+
+        this.ruleBase.addPackage( pkg2 );
+        // packages merged, so still 1 package
+        assertLength( 1,
+                      this.ruleBase.getPackages() );
+        // globals merged, so 3 globals total
+        assertLength( 3,
+                      this.ruleBase.getGlobals().values() );
+        // three globals in the package also
+        assertLength( 3,
+                      this.ruleBase.getPackages()[0].getGlobals().values() );
+
+        this.ruleBase.addPackage( pkg3 );
+        // new package, so now we have 2 package
+        assertLength( 2,
+                      this.ruleBase.getPackages() );
+        // globals partially merged, so 4 globals total
+        assertLength( 4,
+                      this.ruleBase.getGlobals().values() );
+        // two globals in the package
+        final org.drools.rule.Package[] pkgs = this.ruleBase.getPackages();
+        for ( int i = 0; i < pkgs.length; i++ ) {
+            if ( pkgs[i].getName().equals( pkg3.getName() ) ) {
+                assertLength( 2,
+                              pkgs[i].getGlobals().values() );
+            }
+        }
+    }
+
+    public void testRemovePackage() throws Exception {
+        final org.drools.rule.Package pkg1 = new org.drools.rule.Package( "org.droos.test" );
+        pkg1.addGlobal( "global1",
+                        Object.class );
+        pkg1.addGlobal( "global2",
+                        Object.class );
+
+        final org.drools.rule.Package pkg2 = new org.drools.rule.Package( "org.droos.test" );
+        pkg2.addGlobal( "global1",
+                        Object.class );
+        pkg2.addGlobal( "global3",
+                        Object.class );
+
+        final org.drools.rule.Package pkg3 = new org.drools.rule.Package( "org.droos.test2" );
+        pkg3.addGlobal( "global3",
+                        Object.class );
+        pkg3.addGlobal( "global4",
+                        Object.class );
+
+        this.ruleBase.addPackage( pkg1 );
+        this.ruleBase.addPackage( pkg2 );
+        this.ruleBase.addPackage( pkg3 );
+
+        this.ruleBase.removePackage( pkg1.getName() );
+        // packages were partially merged when adding, so removal 
+        // shall left only package 3 behind
+        assertLength( 1,
+                      this.ruleBase.getPackages() );
+        assertLength( 2,
+                      this.ruleBase.getGlobals().values() );
+
+        this.ruleBase.removePackage( pkg3.getName() );
+        assertLength( 0,
+                      this.ruleBase.getPackages() );
+        assertLength( 0,
+                      this.ruleBase.getGlobals().values() );
+
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ReteooWorkingMemoryTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ReteooWorkingMemoryTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/ReteooWorkingMemoryTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,121 @@
+package org.drools.reteoo;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.drools.Cheese;
+import org.drools.FactHandle;
+import org.drools.Person;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.StatefulSession;
+import org.drools.base.MapGlobalResolver;
+import org.drools.common.EqualityKey;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.TruthMaintenanceSystem;
+import org.drools.examples.manners.Guest;
+import org.drools.spi.GlobalResolver;
+
+public class ReteooWorkingMemoryTest extends TestCase {
+    /*
+     * @see JBRULES-356
+     */
+    public void testBasicWorkingMemoryActions() {
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) RuleBaseFactory.newRuleBase().newStatefulSession();
+        final TruthMaintenanceSystem tms = workingMemory.getTruthMaintenanceSystem();
+        final String string = "test";
+        FactHandle fd = workingMemory.insert( string );
+
+        assertEquals( 1,
+                      tms.getAssertMap().size() );
+        EqualityKey key = tms.get( string );
+        assertSame( fd,
+                    key.getFactHandle() );
+        assertNull( key.getOtherFactHandle() );
+
+        workingMemory.update( fd,
+                                    string );
+
+        assertEquals( 1,
+                      tms.getAssertMap().size() );
+        key = tms.get( string );
+        assertSame( fd,
+                    key.getFactHandle() );
+        assertNull( key.getOtherFactHandle() );
+
+        workingMemory.retract( fd );
+
+        assertEquals( 0,
+                      tms.getAssertMap().size() );
+        key = tms.get( string );
+        assertNull( key );
+
+        fd = workingMemory.insert( string );
+
+        assertEquals( 1,
+                      tms.getAssertMap().size() );
+
+        assertEquals( 1,
+                      tms.getAssertMap().size() );
+        key = tms.get( string );
+        assertSame( fd,
+                    key.getFactHandle() );
+        assertNull( key.getOtherFactHandle() );
+    }
+
+    public void testId() {
+        final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        InternalWorkingMemory workingMemory = (InternalWorkingMemory) ruleBase.newStatefulSession();
+        assertEquals( 0,
+                      workingMemory.getId() );
+        workingMemory = (InternalWorkingMemory) ruleBase.newStatefulSession();
+        assertEquals( 1,
+                      workingMemory.getId() );
+    }
+
+    public void testGlobalResolver() {
+        final Map map = new HashMap();
+        map.put( "global1",
+                 "value1" );
+        map.put( "global2",
+                 "value2" );
+        final GlobalResolver resolver = new MapGlobalResolver(map);
+        final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        final InternalWorkingMemory workingMemory = (InternalWorkingMemory) ruleBase.newStatefulSession();
+        workingMemory.setGlobalResolver( resolver );
+        assertEquals( "value1",
+                      workingMemory.getGlobal( "global1" ) );
+        assertEquals( "value2",
+                      workingMemory.getGlobal( "global2" ) );
+    }
+    
+    public void testObjectIterator() {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+        final StatefulSession session = ruleBase.newStatefulSession();
+        
+        session.insert( new Person( "bob", 35) );
+        session.insert( new Cheese( "stilton", 35) );
+        session.insert( new Cheese( "brie", 35) );
+        session.insert( new Person( "steve", 55) );
+        session.insert( new Person( "tom", 100) );
+        
+        int i = 0;
+        for ( Iterator it = session.iterateFactHandles(); it.hasNext(); ) {
+            Object object = it.next();
+            if ( i++ > 5 ) {
+                fail( "should not iterate for than 3 times" );
+            }
+        }
+        
+        i = 0;
+        for ( Iterator it = session.iterateObjects(); it.hasNext(); ) {
+            Object object = it.next();
+            if ( i++ > 5 ) {
+                fail( "should not iterate for than 3 times" );
+            }
+        }               
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/RuleFlowGroupTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/RuleFlowGroupTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/RuleFlowGroupTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,598 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.DroolsTestCase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.base.SalienceInteger;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalAgenda;
+import org.drools.common.PropagationContextImpl;
+import org.drools.common.RuleFlowGroupImpl;
+import org.drools.process.instance.ProcessInstance;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.Rule;
+import org.drools.ruleflow.core.RuleFlowProcess;
+import org.drools.ruleflow.instance.RuleFlowProcessInstance;
+import org.drools.spi.Consequence;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.PropagationContext;
+import org.drools.workflow.core.Connection;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.impl.ConnectionImpl;
+import org.drools.workflow.core.node.EndNode;
+import org.drools.workflow.core.node.Join;
+import org.drools.workflow.core.node.RuleSetNode;
+import org.drools.workflow.core.node.Split;
+import org.drools.workflow.core.node.StartNode;
+import org.drools.workflow.instance.impl.ConstraintEvaluator;
+
+/**
+ * @author mproctor
+ */
+
+public class RuleFlowGroupTest extends DroolsTestCase {
+    private ReteooRuleBase ruleBase;
+    private BuildContext   buildContext;
+
+    protected void setUp() throws Exception {
+        ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        buildContext = new BuildContext( ruleBase,
+                                         ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator() );
+    }
+
+    public void testRuleFlowGroup() {
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+        final List list = new ArrayList();
+
+        // create the consequence
+        final Consequence consequence = new Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory workingMemory) {
+                list.add( knowledgeHelper.getRule() );
+            }
+        };
+
+        // create a rule for each rule flow groups
+        final Rule rule0 = new Rule( "test-rule0" );
+        rule0.setRuleFlowGroup( "rule-flow-group-0" );
+        rule0.setConsequence( consequence );
+
+        final RuleTerminalNode node0 = new RuleTerminalNode( 3,
+                                                             new MockTupleSource( 2 ),
+                                                             rule0,
+                                                             rule0.getLhs(),
+                                                             buildContext );
+
+        final Rule rule1 = new Rule( "test-rule1" );
+        rule1.setRuleFlowGroup( "rule-flow-group-1" );
+        rule1.setConsequence( consequence );
+
+        final RuleTerminalNode node1 = new RuleTerminalNode( 4,
+                                                             new MockTupleSource( 2 ),
+                                                             rule1,
+                                                             rule1.getLhs(),
+                                                             buildContext );
+
+        final Rule rule2 = new Rule( "test-rule2" );
+        rule2.setRuleFlowGroup( "rule-flow-group-2" );
+        rule2.setConsequence( consequence );
+        rule2.setSalience( new SalienceInteger( 10 ) );
+
+        final RuleTerminalNode node2 = new RuleTerminalNode( 5,
+                                                             new MockTupleSource( 2 ),
+                                                             rule2,
+                                                             rule2.getLhs(),
+                                                             buildContext );
+
+        final Rule rule3 = new Rule( "test-rule3" );
+        rule3.setRuleFlowGroup( "rule-flow-group-3" );
+        rule3.setConsequence( consequence );
+
+        final RuleTerminalNode node3 = new RuleTerminalNode( 6,
+                                                             new MockTupleSource( 2 ),
+                                                             rule3,
+                                                             rule3.getLhs(),
+                                                             buildContext );
+
+        final PropagationContext context0 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule0,
+                                                                        null );
+
+        // nodes
+        final StartNode start = new StartNode();
+        final RuleSetNode ruleSet0 = new RuleSetNode();
+        ruleSet0.setRuleFlowGroup( "rule-flow-group-0" );
+        final RuleSetNode ruleSet1 = new RuleSetNode();
+        ruleSet1.setRuleFlowGroup( "rule-flow-group-1" );
+        final RuleSetNode ruleSet2 = new RuleSetNode();
+        ruleSet2.setRuleFlowGroup( "rule-flow-group-2" );
+        final RuleSetNode ruleSet3 = new RuleSetNode();
+        ruleSet3.setRuleFlowGroup( "rule-flow-group-3" );
+        final Split split = new Split();
+        split.setType( Split.TYPE_AND );
+        final Join join = new Join();
+        join.setType( Join.TYPE_AND );
+        final EndNode end = new EndNode();
+        // connections
+        new ConnectionImpl( start,
+                            Node.CONNECTION_DEFAULT_TYPE,
+                            ruleSet0,
+                            Node.CONNECTION_DEFAULT_TYPE);
+        new ConnectionImpl( ruleSet0,
+                            Node.CONNECTION_DEFAULT_TYPE,
+                            split,
+                            Node.CONNECTION_DEFAULT_TYPE);
+        new ConnectionImpl( split,
+                            Node.CONNECTION_DEFAULT_TYPE,
+                            ruleSet1,
+                            Node.CONNECTION_DEFAULT_TYPE);
+        new ConnectionImpl( split,
+                            Node.CONNECTION_DEFAULT_TYPE,
+                            ruleSet2,
+                            Node.CONNECTION_DEFAULT_TYPE);
+        new ConnectionImpl( ruleSet1,
+                            Node.CONNECTION_DEFAULT_TYPE,
+                            join,
+                            Node.CONNECTION_DEFAULT_TYPE);
+        new ConnectionImpl( ruleSet2,
+                            Node.CONNECTION_DEFAULT_TYPE,
+                            join,
+                            Node.CONNECTION_DEFAULT_TYPE);
+        new ConnectionImpl( join,
+                            Node.CONNECTION_DEFAULT_TYPE,
+                            ruleSet3,
+                            Node.CONNECTION_DEFAULT_TYPE);
+        new ConnectionImpl( ruleSet3,
+                            Node.CONNECTION_DEFAULT_TYPE,
+                            end,
+                            Node.CONNECTION_DEFAULT_TYPE);
+
+        // process
+        final RuleFlowProcess process = new RuleFlowProcess();
+        process.addNode( start );
+        process.addNode( ruleSet0 );
+        process.addNode( ruleSet1 );
+        process.addNode( ruleSet2 );
+        process.addNode( ruleSet3 );
+        process.addNode( split );
+        process.addNode( join );
+        process.addNode( end );
+
+        // proces instance
+        final RuleFlowProcessInstance processInstance = new RuleFlowProcessInstance();
+        processInstance.setWorkingMemory( workingMemory );
+        processInstance.setProcess( process );
+        assertEquals( ProcessInstance.STATE_PENDING,
+                      processInstance.getState() );
+
+        final RuleFlowGroupImpl ruleFlowGroup0 = (RuleFlowGroupImpl) agenda.getRuleFlowGroup( "rule-flow-group-0" );
+        final RuleFlowGroupImpl ruleFlowGroup1 = (RuleFlowGroupImpl) agenda.getRuleFlowGroup( "rule-flow-group-1" );
+        final RuleFlowGroupImpl ruleFlowGroup2 = (RuleFlowGroupImpl) agenda.getRuleFlowGroup( "rule-flow-group-2" );
+        final RuleFlowGroupImpl ruleFlowGroup3 = (RuleFlowGroupImpl) agenda.getRuleFlowGroup( "rule-flow-group-3" );
+
+        final ReteTuple tuple0 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+        node0.assertTuple( tuple0,
+                           context0,
+                           workingMemory );
+
+        final ReteTuple tuple1 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+        node0.assertTuple( tuple1,
+                           context0,
+                           workingMemory );
+
+        final ReteTuple tuple2 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+        node1.assertTuple( tuple2,
+                           context0,
+                           workingMemory );
+
+        final ReteTuple tuple3 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+        node2.assertTuple( tuple3,
+                           context0,
+                           workingMemory );
+
+        final ReteTuple tuple4 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+        node3.assertTuple( tuple4,
+                           context0,
+                           workingMemory );
+
+        // RuleFlowGroups should be populated, but the agenda shouldn't
+        assertEquals( 2,
+                      ruleFlowGroup0.size() );
+        assertEquals( 1,
+                      ruleFlowGroup1.size() );
+        assertEquals( 1,
+                      ruleFlowGroup2.size() );
+        assertEquals( 1,
+                      ruleFlowGroup3.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+
+        // Activate process instance, the activations stay in the group,
+        // but should now also be in the Agenda
+        processInstance.start();
+        assertEquals( ProcessInstance.STATE_ACTIVE,
+                      processInstance.getState() );
+        assertEquals( 2,
+                      ruleFlowGroup0.size() );
+        assertEquals( 2,
+                      agenda.agendaSize() );
+
+        // As we fire each rule they are removed from both the Agenda and the RuleFlowGroup
+        agenda.fireNextItem( null );
+        assertEquals( 1,
+                      ruleFlowGroup0.size() );
+        assertEquals( 1,
+                      agenda.agendaSize() );
+
+        // on firing the last activation the child rule flow groups should 
+        // activate and thus repopulate the agenda
+        agenda.fireNextItem( null );
+        workingMemory.executeQueuedActions();
+        assertEquals( 0,
+                      ruleFlowGroup0.size() );
+        assertEquals( 1,
+                      ruleFlowGroup1.size() );
+        assertEquals( 1,
+                      ruleFlowGroup2.size() );
+        assertEquals( 2,
+                      agenda.agendaSize() );
+
+        // we set the salience higher on rule2, so it sould fire first and empty ruleFlowGroup2
+        agenda.fireNextItem( null );
+        assertEquals( 1,
+                      ruleFlowGroup1.size() );
+        assertEquals( 0,
+                      ruleFlowGroup2.size() );
+        assertEquals( 1,
+                      agenda.agendaSize() );
+
+        // executing rule1, which should activate AND-join and thus group 3 
+        agenda.fireNextItem( null );
+        workingMemory.executeQueuedActions();
+        assertEquals( 0,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      ruleFlowGroup1.size() );
+        assertEquals( 0,
+                      ruleFlowGroup2.size() );
+        assertEquals( 1,
+                      ruleFlowGroup3.size() );
+        assertEquals( 1,
+                      agenda.agendaSize() );
+
+        // executing rule3, and finishing execution
+        agenda.fireNextItem( null );
+        workingMemory.executeQueuedActions();
+        assertEquals( 0,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      ruleFlowGroup1.size() );
+        assertEquals( 0,
+                      ruleFlowGroup2.size() );
+        assertEquals( 0,
+                      ruleFlowGroup3.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+        assertEquals( ProcessInstance.STATE_COMPLETED,
+                      processInstance.getState() );
+    }
+
+    /** XOR split and join */
+    public void testRuleFlowGroup2() {
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+        final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+        final List list = new ArrayList();
+
+        // create the consequence
+        final Consequence consequence = new Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory workingMemory) {
+                list.add( knowledgeHelper.getRule() );
+            }
+        };
+
+        // create a rule for each rule flow groups
+        final Rule rule0 = new Rule( "test-rule0" );
+        rule0.setRuleFlowGroup( "rule-flow-group-0" );
+        rule0.setConsequence( consequence );
+
+        final RuleTerminalNode node0 = new RuleTerminalNode( 3,
+                                                             new MockTupleSource( 2 ),
+                                                             rule0,
+                                                             rule0.getLhs(),
+                                                             buildContext );
+
+        final Rule rule1 = new Rule( "test-rule1" );
+        rule1.setRuleFlowGroup( "rule-flow-group-1" );
+        rule1.setConsequence( consequence );
+
+        final RuleTerminalNode node1 = new RuleTerminalNode( 4,
+                                                             new MockTupleSource( 2 ),
+                                                             rule1,
+                                                             rule1.getLhs(),
+                                                             buildContext );
+
+        final Rule rule2 = new Rule( "test-rule2" );
+        rule2.setRuleFlowGroup( "rule-flow-group-2" );
+        rule2.setConsequence( consequence );
+        rule2.setSalience( new SalienceInteger( 10 ) );
+
+        final RuleTerminalNode node2 = new RuleTerminalNode( 5,
+                                                             new MockTupleSource( 2 ),
+                                                             rule2,
+                                                             rule2.getLhs(),
+                                                             buildContext );
+
+        final Rule rule3 = new Rule( "test-rule3" );
+        rule3.setRuleFlowGroup( "rule-flow-group-3" );
+        rule3.setConsequence( consequence );
+
+        final RuleTerminalNode node3 = new RuleTerminalNode( 6,
+                                                             new MockTupleSource( 2 ),
+                                                             rule3,
+                                                             rule3.getLhs(),
+                                                             buildContext );
+
+        final PropagationContext context0 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule0,
+                                                                        null );
+
+        // nodes
+        final StartNode start = new StartNode();
+        final RuleSetNode ruleSet0 = new RuleSetNode();
+        ruleSet0.setRuleFlowGroup( "rule-flow-group-0" );
+        final RuleSetNode ruleSet1 = new RuleSetNode();
+        ruleSet1.setRuleFlowGroup( "rule-flow-group-1" );
+        final RuleSetNode ruleSet2 = new RuleSetNode();
+        ruleSet2.setRuleFlowGroup( "rule-flow-group-2" );
+        final RuleSetNode ruleSet3 = new RuleSetNode();
+        ruleSet3.setRuleFlowGroup( "rule-flow-group-3" );
+        final Split split = new Split();
+        split.setType( Split.TYPE_XOR );
+        final Join join = new Join();
+        join.setType( Join.TYPE_XOR );
+        final EndNode end = new EndNode();
+        // connections
+        new ConnectionImpl( start,
+                            Node.CONNECTION_DEFAULT_TYPE,
+                            ruleSet0,
+                            Node.CONNECTION_DEFAULT_TYPE);
+        new ConnectionImpl( ruleSet0,
+                            Node.CONNECTION_DEFAULT_TYPE,
+                            split,
+                            Node.CONNECTION_DEFAULT_TYPE);
+        Connection out1 = new ConnectionImpl( split,
+                                              Node.CONNECTION_DEFAULT_TYPE,
+                                              ruleSet1,
+                                              Node.CONNECTION_DEFAULT_TYPE);
+        Connection out2 = new ConnectionImpl( split,
+                                              Node.CONNECTION_DEFAULT_TYPE,
+                                              ruleSet2,
+                                              Node.CONNECTION_DEFAULT_TYPE);
+        new ConnectionImpl( ruleSet1,
+                            Node.CONNECTION_DEFAULT_TYPE,
+                            join,
+                            Node.CONNECTION_DEFAULT_TYPE);
+        new ConnectionImpl( ruleSet2,
+                            Node.CONNECTION_DEFAULT_TYPE,
+                            join,
+                            Node.CONNECTION_DEFAULT_TYPE);
+        new ConnectionImpl( join,
+                            Node.CONNECTION_DEFAULT_TYPE,
+                            ruleSet3,
+                            Node.CONNECTION_DEFAULT_TYPE);
+        new ConnectionImpl( ruleSet3,
+                            Node.CONNECTION_DEFAULT_TYPE,
+                            end,
+                            Node.CONNECTION_DEFAULT_TYPE);
+        ConstraintEvaluator constraint1 = new org.drools.workflow.instance.impl.RuleConstraintEvaluator();
+        constraint1.setPriority( 1 );
+        split.setConstraint( out1,
+                             constraint1 );
+        ConstraintEvaluator constraint2 = new org.drools.workflow.instance.impl.RuleConstraintEvaluator();
+        constraint2.setPriority( 2 );
+        split.setConstraint( out2,
+                             constraint2 );
+
+        // process
+        final RuleFlowProcess process = new RuleFlowProcess();
+        process.setId( "1" );
+        process.addNode( start );
+        process.addNode( ruleSet0 );
+        process.addNode( ruleSet1 );
+        process.addNode( ruleSet2 );
+        process.addNode( ruleSet3 );
+        process.addNode( split );
+        process.addNode( join );
+        process.addNode( end );
+
+        // rules for split
+        final Rule splitRule1 = new Rule( "RuleFlow-Split-1-" + split.getId() + "-" + ruleSet1.getId() );
+        splitRule1.setRuleFlowGroup( "DROOLS_SYSTEM" );
+        splitRule1.setConsequence( consequence );
+
+        final RuleTerminalNode splitNode1 = new RuleTerminalNode( 7,
+                                                                  new MockTupleSource( 2 ),
+                                                                  splitRule1,
+                                                                  splitRule1.getLhs(),
+                                                                  buildContext );
+
+        final Rule splitRule2 = new Rule( "RuleFlow-Split-1-" + split.getId() + "-" + ruleSet2.getId() );
+        splitRule2.setRuleFlowGroup( "DROOLS_SYSTEM" );
+        splitRule2.setConsequence( consequence );
+
+        final RuleTerminalNode splitNode2 = new RuleTerminalNode( 8,
+                                                                  new MockTupleSource( 2 ),
+                                                                  splitRule2,
+                                                                  splitRule2.getLhs(),
+                                                                  buildContext );
+
+        // proces instance
+        final RuleFlowProcessInstance processInstance = new RuleFlowProcessInstance();
+        processInstance.setWorkingMemory( workingMemory );
+        processInstance.setProcess( process );
+        assertEquals( ProcessInstance.STATE_PENDING,
+                      processInstance.getState() );
+
+        final RuleFlowGroupImpl ruleFlowGroup0 = (RuleFlowGroupImpl) agenda.getRuleFlowGroup( "rule-flow-group-0" );
+        final RuleFlowGroupImpl ruleFlowGroup1 = (RuleFlowGroupImpl) agenda.getRuleFlowGroup( "rule-flow-group-1" );
+        final RuleFlowGroupImpl ruleFlowGroup2 = (RuleFlowGroupImpl) agenda.getRuleFlowGroup( "rule-flow-group-2" );
+        final RuleFlowGroupImpl ruleFlowGroup3 = (RuleFlowGroupImpl) agenda.getRuleFlowGroup( "rule-flow-group-3" );
+
+        final ReteTuple tuple0 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+        node0.assertTuple( tuple0,
+                           context0,
+                           workingMemory );
+
+        final ReteTuple tuple1 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+        node0.assertTuple( tuple1,
+                           context0,
+                           workingMemory );
+
+        final ReteTuple tuple2 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+        node1.assertTuple( tuple2,
+                           context0,
+                           workingMemory );
+
+        final ReteTuple tuple3 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+        node2.assertTuple( tuple3,
+                           context0,
+                           workingMemory );
+
+        final ReteTuple tuple4 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+        node3.assertTuple( tuple4,
+                           context0,
+                           workingMemory );
+
+        final ReteTuple splitTuple1 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                            "cheese" ) );
+        splitNode1.assertTuple( splitTuple1,
+                                context0,
+                                workingMemory );
+
+        final ReteTuple splitTuple2 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                            "cheese" ) );
+        splitNode2.assertTuple( splitTuple2,
+                                context0,
+                                workingMemory );
+
+        final RuleFlowGroupImpl systemRuleFlowGroup = (RuleFlowGroupImpl) agenda.getRuleFlowGroup( "DROOLS_SYSTEM" );
+
+        // RuleFlowGroups should be populated, but the agenda shouldn't
+        assertEquals( 2,
+                      ruleFlowGroup0.size() );
+        assertEquals( 1,
+                      ruleFlowGroup1.size() );
+        assertEquals( 1,
+                      ruleFlowGroup2.size() );
+        assertEquals( 1,
+                      ruleFlowGroup3.size() );
+        assertEquals( 2,
+                      systemRuleFlowGroup.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+
+        // Activate process instance, the activations stay in the group,
+        // but should now also be in the Agenda
+        processInstance.start();
+        assertEquals( ProcessInstance.STATE_ACTIVE,
+                      processInstance.getState() );
+        assertEquals( 2,
+                      ruleFlowGroup0.size() );
+        assertEquals( 2,
+                      agenda.agendaSize() );
+
+        // As we fire each rule they are removed from both the Agenda and the RuleFlowGroup
+        agenda.fireNextItem( null );
+        assertEquals( 1,
+                      ruleFlowGroup0.size() );
+        assertEquals( 1,
+                      agenda.agendaSize() );
+
+        // XOR split should activate group1
+        agenda.fireNextItem( null );
+        workingMemory.executeQueuedActions();
+        assertEquals( 0,
+                      ruleFlowGroup0.size() );
+        assertEquals( 1,
+                      ruleFlowGroup1.size() );
+        assertEquals( 1,
+                      ruleFlowGroup2.size() );
+        assertEquals( 1,
+                      agenda.agendaSize() );
+
+        // executing group1, XOR join should activate group3 
+        agenda.fireNextItem( null );
+        workingMemory.executeQueuedActions();
+        assertEquals( 0,
+                      ruleFlowGroup1.size() );
+        assertEquals( 1,
+                      ruleFlowGroup2.size() );
+        assertEquals( 1,
+                      ruleFlowGroup3.size() );
+        assertEquals( 1,
+                      agenda.agendaSize() );
+
+        // executing rule3, and finishing execution
+        agenda.fireNextItem( null );
+        workingMemory.executeQueuedActions();
+        assertEquals( 0,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      ruleFlowGroup1.size() );
+        assertEquals( 1,
+                      ruleFlowGroup2.size() );
+        assertEquals( 0,
+                      ruleFlowGroup3.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+        assertEquals( ProcessInstance.STATE_COMPLETED,
+                      processInstance.getState() );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/SchedulerTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/SchedulerTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/SchedulerTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,334 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.Agenda;
+import org.drools.DroolsTestCase;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.reteoo.ReteooBuilder.IdGenerator;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.Rule;
+import org.drools.spi.Duration;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
+
+/**
+ * @author mproctor
+ */
+
+public class SchedulerTest extends DroolsTestCase {
+    private ReteooRuleBase ruleBase;
+    private BuildContext buildContext;
+    
+    protected void setUp() throws Exception {
+        ruleBase = ( ReteooRuleBase ) RuleBaseFactory.newRuleBase();
+        buildContext = new BuildContext( ruleBase, ((ReteooRuleBase)ruleBase).getReteooBuilder().getIdGenerator() );
+    }
+    
+    
+    public void testScheduledActivation() throws Exception {
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
+        InternalWorkingMemory workingMemory = ( InternalWorkingMemory ) ruleBase.newStatefulSession();
+
+        final Rule rule = new Rule( "test-rule" );
+        final RuleTerminalNode node = new RuleTerminalNode( idGenerator.getNextId(),
+                                                            new MockTupleSource( idGenerator.getNextId() ),
+                                                            rule,
+                                                            rule.getLhs(),
+                                                            buildContext );
+        final List data = new ArrayList();
+
+        // add consequence
+        rule.setConsequence( new org.drools.spi.Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(final KnowledgeHelper knowledgeHelper,
+                                 final WorkingMemory workingMemory) {
+                data.add( "tested" );
+            }
+        } );
+
+        /* 1/10th of a second */
+        final Duration duration = new Duration() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public long getDuration(Tuple tuple) {
+                return 100;
+            }
+
+        };
+        rule.setDuration( duration );
+
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+
+        final ReteTuple tuple = new ReteTuple( new DefaultFactHandle( 1,
+                                                                      "cheese" ) );
+
+        assertEquals( 0,
+                      data.size() );
+
+        node.assertTuple( tuple,
+                          context,
+                          workingMemory );
+
+        // sleep for 300ms
+        Thread.sleep( 300 );
+
+        // now check for update
+        assertEquals( 1,
+                      data.size() );
+    }
+
+    public void testDoLoopScheduledActivation() throws Exception {
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
+
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+        final Agenda agenda = workingMemory.getAgenda();
+
+        final Rule rule = new Rule( "test-rule" );
+        final RuleTerminalNode node = new RuleTerminalNode( idGenerator.getNextId(),
+                                                            new MockTupleSource( idGenerator.getNextId() ),
+                                                            rule,
+                                                            rule.getLhs(),
+                                                            buildContext );
+        final List data = new ArrayList();
+
+        /* 1/10th of a second */
+        final Duration duration = new Duration() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public long getDuration(Tuple tuple) {
+                return 100;
+            }
+
+        };
+
+        rule.setDuration( duration );
+
+        // add consequence
+        rule.setConsequence( new org.drools.spi.Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(final KnowledgeHelper knowledgeHelper,
+                                 final WorkingMemory workingMemory) {
+                /* on first invoke add another one to the agenda */
+                if ( data.size() < 3 ) {
+                    final PropagationContext context2 = new PropagationContextImpl( 0,
+                                                                                    0,
+                                                                                    rule,
+                                                                                    knowledgeHelper.getActivation() );
+                    final ReteTuple tuple2 = new ReteTuple( new DefaultFactHandle( 2,
+                                                                                   "cheese" ) );
+                    node.assertTuple( tuple2,
+                                      context2,
+                                      (ReteooWorkingMemory) workingMemory );
+                }
+                data.add( "tested" );
+            }
+        } );
+
+        final PropagationContext context1 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        null,
+                                                                        null );
+
+        final ReteTuple tuple1 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+
+        node.assertTuple( tuple1,
+                          context1,
+                          workingMemory );
+
+        assertEquals( 0,
+                      data.size() );
+
+        // sleep for 0.5 seconds
+        Thread.sleep( 500 );
+
+        // now check for update
+        assertEquals( 4,
+                      data.size() );
+
+    }
+
+    public void testNoLoopScheduledActivation() throws Exception {
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
+
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+        final Agenda agenda = workingMemory.getAgenda();
+
+        final Rule rule = new Rule( "test-rule" );
+        final List data = new ArrayList();
+
+        final RuleTerminalNode node = new RuleTerminalNode( idGenerator.getNextId(),
+                                                            new MockTupleSource( idGenerator.getNextId() ),
+                                                            rule,
+                                                            rule.getLhs(),
+                                                            buildContext );
+
+        /* 1/10th of a second */
+        final Duration duration = new Duration() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public long getDuration(Tuple tuple) {
+                return 100;
+            }
+
+        };
+
+        rule.setDuration( duration );
+        rule.setNoLoop( true );
+
+        // add consequence
+        rule.setConsequence( new org.drools.spi.Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public void evaluate(final KnowledgeHelper knowledgeHelper,
+                                 final WorkingMemory workingMemory) {
+                /* on first invoke add another one to the agenda */
+                if ( data.size() < 5 ) {
+                    final PropagationContext context2 = new PropagationContextImpl( 0,
+                                                                                    0,
+                                                                                    rule,
+                                                                                    knowledgeHelper.getActivation() );
+                    final ReteTuple tuple2 = new ReteTuple( new DefaultFactHandle( 2,
+                                                                                   "cheese" ) );
+                    node.assertTuple( tuple2,
+                                      context2,
+                                      (ReteooWorkingMemory) workingMemory );
+                }
+                data.add( "tested" );
+            }
+        } );
+
+        final PropagationContext context1 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        null,
+                                                                        null );
+
+        final ReteTuple tuple1 = new ReteTuple( new DefaultFactHandle( 1,
+                                                                       "cheese" ) );
+        node.assertTuple( tuple1,
+                          context1,
+                          workingMemory );
+        assertEquals( 0,
+                      data.size() );
+
+        // sleep for 0.5 seconds
+        Thread.sleep( 500 );
+
+        // now check for update
+        assertEquals( 1,
+                      data.size() );
+
+    }
+    //
+    //    public void testExceptionHandler() throws Exception {
+    //        RuleBase ruleBase = new RuleBaseImpl();
+    //
+    //        WorkingMemoryImpl workingMemory = (WorkingMemoryImpl) ruleBase.newWorkingMemory();
+    //        Agenda agenda = workingMemory.getAgenda();
+    //        final Scheduler scheduler = Scheduler.getInstance();
+    //
+    //        final Rule rule = new Rule( "test-rule" );
+    //
+    //        // add consequence
+    //        rule.setConsequence( new org.drools.spi.Consequence() {
+    //            public void invoke(Activation activation,
+    //                               WorkingMemory workingMemory) throws ConsequenceException {
+    //                throw new ConsequenceException( "not enough cheese",
+    //                                                rule );
+    //            }
+    //        } );
+    //
+    //        /* 1/10th of a second */
+    //        Duration duration = new Duration() {
+    //            public long getDuration(Tuple tuple) {
+    //                return 100;
+    //            }
+    //
+    //        };
+    //        rule.setDuration( duration );
+    //
+    //        final List data = new ArrayList();
+    //
+    //        PropagationContext context = new PropagationContextImpl( 0,
+    //                                                                 PropagationContext.ASSERTION,
+    //                                                                 null,
+    //                                                                 null );
+    //
+    //        ReteTuple tuple = new ReteTuple( 0,
+    //                                         new FactHandleImpl( 1 ),
+    //                                         workingMemory );
+    //
+    //        assertEquals( 0,
+    //                      data.size() );
+    //
+    //        AsyncExceptionHandler handler = new AsyncExceptionHandler() {
+    //            public void handleException(WorkingMemory workingMemory,
+    //                                        ConsequenceException exception) {
+    //                data.add( "tested" );
+    //            }
+    //        };
+    //        workingMemory.setAsyncExceptionHandler( handler );
+    //
+    //        assertLength( 0,
+    //                      data );
+    //
+    //        agenda.addToAgenda( tuple,
+    //                            context,
+    //                            rule );
+    //
+    //        // sleep for 2 seconds
+    //        Thread.sleep( 300 );
+    //
+    //        // now check for update
+    //        assertLength( 1,
+    //                      data );
+    //    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/TupleSourceTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/TupleSourceTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/TupleSourceTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,86 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.Field;
+
+import org.drools.DroolsTestCase;
+
+public class TupleSourceTest extends DroolsTestCase {
+
+    public void testObjectTupleConstructor() {
+        final MockTupleSource source = new MockTupleSource( 15 );
+        assertEquals( 15,
+                      source.getId() );
+    }
+
+    public void testAddTupleSink() throws Exception {
+        final MockTupleSource source = new MockTupleSource( 15 );
+
+        // We need to re-assign this var each time the sink changes references
+        final Field field = TupleSource.class.getDeclaredField( "sink" );
+        field.setAccessible( true );
+        TupleSinkPropagator sink = (TupleSinkPropagator) field.get( source );
+
+        assertSame( EmptyTupleSinkAdapter.getInstance(),
+                    sink );
+
+        final MockTupleSink sink1 = new MockTupleSink();
+        source.addTupleSink( sink1 );
+        sink = (TupleSinkPropagator) field.get( source );
+        assertSame( SingleTupleSinkAdapter.class,
+                    sink.getClass() );
+        assertEquals( 1,
+                      sink.getSinks().length );
+
+        final MockTupleSink sink2 = new MockTupleSink();
+        source.addTupleSink( sink2 );
+        sink = (TupleSinkPropagator) field.get( source );
+        assertSame( CompositeTupleSinkAdapter.class,
+                    sink.getClass() );
+        assertEquals( 2,
+                      sink.getSinks().length );
+
+        final MockTupleSink sink3 = new MockTupleSink();
+        source.addTupleSink( sink3 );
+        assertSame( CompositeTupleSinkAdapter.class,
+                    sink.getClass() );
+        assertEquals( 3,
+                      sink.getSinks().length );
+
+        source.removeTupleSink( sink2 );
+        assertSame( CompositeTupleSinkAdapter.class,
+                    sink.getClass() );
+        assertEquals( 2,
+                      sink.getSinks().length );
+
+        source.removeTupleSink( sink1 );
+        sink = (TupleSinkPropagator) field.get( source );
+        assertSame( SingleTupleSinkAdapter.class,
+                    sink.getClass() );
+        assertEquals( 1,
+                      sink.getSinks().length );
+
+        source.removeTupleSink( sink3 );
+        sink = (TupleSinkPropagator) field.get( source );
+        assertSame( EmptyTupleSinkAdapter.getInstance(),
+                    sink );
+        assertEquals( 0,
+                      sink.getSinks().length );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/builder/ReteooRuleBuilderTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/builder/ReteooRuleBuilderTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/reteoo/builder/ReteooRuleBuilderTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2006 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.builder;
+
+import java.util.List;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.drools.WorkingMemory;
+import org.drools.base.ClassObjectType;
+import org.drools.reteoo.ReteooBuilder;
+import org.drools.reteoo.ReteooRuleBase;
+import org.drools.reteoo.RuleTerminalNode;
+import org.drools.reteoo.ReteooBuilder.IdGenerator;
+import org.drools.rule.Package;
+import org.drools.rule.Pattern;
+import org.drools.rule.GroupElement;
+import org.drools.rule.GroupElementFactory;
+import org.drools.rule.Rule;
+import org.drools.spi.Consequence;
+import org.drools.spi.KnowledgeHelper;
+
+/**
+ * @author etirelli
+ *
+ */
+public class ReteooRuleBuilderTest extends TestCase {
+    private ReteooRuleBuilder builder;
+    private ReteooRuleBase    rulebase;
+
+    /* (non-Javadoc)
+     * @see junit.framework.TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        this.builder = new ReteooRuleBuilder();
+        this.rulebase = new ReteooRuleBase( "default" );
+    }
+
+    /* (non-Javadoc)
+     * @see junit.framework.TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * Test method for {@link org.drools.reteoo.builder.ReteooRuleBuilder#addRule(org.drools.rule.Rule, org.drools.reteoo.ReteooRuleBase, java.util.Map, int)}.
+     */
+    public void testAddRuleWithPatterns() {
+        final Rule rule = new Rule( "only patterns" );
+        final Pattern c1 = new Pattern( 0,
+                                new ClassObjectType( String.class ) );
+        final Pattern c2 = new Pattern( 1,
+                                new ClassObjectType( String.class ) );
+        final Pattern c3 = new Pattern( 2,
+                                new ClassObjectType( String.class ) );
+
+        final GroupElement lhsroot = GroupElementFactory.newAndInstance();
+        lhsroot.addChild( c1 );
+        lhsroot.addChild( c2 );
+        lhsroot.addChild( c3 );
+
+        rule.setLhs( lhsroot );
+
+        final Consequence consequence = new Consequence() {
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory workingMemory) throws Exception {
+                System.out.println( "Consequence!" );
+            }
+
+        };
+
+        rule.setConsequence( consequence );
+
+        final List terminals = this.builder.addRule( rule,
+                                               this.rulebase,
+                                               new ReteooBuilder.IdGenerator( 1 ) );
+
+        Assert.assertEquals( "Rule must have a single terminal node",
+                             1,
+                             terminals.size() );
+
+        final RuleTerminalNode terminal = (RuleTerminalNode) terminals.get( 0 );
+
+    }
+
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/DeclarationTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/DeclarationTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/DeclarationTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,96 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+
+import junit.framework.TestCase;
+
+import org.drools.Cheese;
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.ClassObjectType;
+import org.drools.spi.FieldExtractor;
+
+public class DeclarationTest extends TestCase {
+
+    ClassFieldExtractorCache cache = ClassFieldExtractorCache.getInstance();
+
+    public void testDeclaration() throws IntrospectionException {
+        final FieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                             "type",
+                                                             getClass().getClassLoader() );
+
+        final Pattern pattern = new Pattern( 5,
+                                             new ClassObjectType( Cheese.class ) );
+
+        // Bind the extractor to a decleration
+        // Declarations know the pattern they derive their value from
+        final Declaration declaration = new Declaration( "typeOfCheese",
+                                                         extractor,
+                                                         pattern );
+
+        assertEquals( "typeOfCheese",
+                      declaration.getIdentifier() );
+
+        assertSame( String.class,
+                    declaration.getExtractor().getExtractToClass() );
+
+        assertSame( extractor,
+                    declaration.getExtractor() );
+
+        assertEquals( 5,
+                      declaration.getPattern().getOffset() );
+
+    }
+
+    public void testGetFieldValue() throws IntrospectionException {
+        final FieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                             "type",
+                                                             getClass().getClassLoader() );
+
+        final Pattern pattern = new Pattern( 5,
+                                             new ClassObjectType( Cheese.class ) );
+
+        // Bind the extractor to a decleration 
+        // Declarations know the pattern they derive their value from 
+        final Declaration declaration = new Declaration( "typeOfCheese",
+                                                         extractor,
+                                                         pattern );
+
+        // Create some facts
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           5 );
+
+        // Check we can extract Declarations correctly
+        assertEquals( "cheddar",
+                      declaration.getValue( null,
+                                            cheddar ) );
+    }
+
+    public static int getIndex(final Class clazz,
+                               final String name) throws IntrospectionException {
+        final PropertyDescriptor[] descriptors = Introspector.getBeanInfo( clazz ).getPropertyDescriptors();
+        for ( int i = 0; i < descriptors.length; i++ ) {
+            if ( descriptors[i].getName().equals( name ) ) {
+                return i;
+            }
+        }
+        return -1;
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/FieldConstraintTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/FieldConstraintTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/FieldConstraintTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,576 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.beans.IntrospectionException;
+
+import junit.framework.TestCase;
+
+import org.drools.Cheese;
+import org.drools.FactHandle;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.base.ClassFieldExtractor;
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.ClassObjectType;
+import org.drools.base.FieldFactory;
+import org.drools.base.ShadowProxy;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.ComparableEvaluatorsDefinition;
+import org.drools.base.evaluators.EqualityEvaluatorsDefinition;
+import org.drools.base.evaluators.Operator;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.InstrumentedReteTuple;
+import org.drools.reteoo.ReteooRuleBase;
+import org.drools.rule.PredicateConstraint.PredicateContextEntry;
+import org.drools.rule.ReturnValueRestriction.ReturnValueContextEntry;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.FieldValue;
+import org.drools.spi.PredicateExpression;
+import org.drools.spi.ReturnValueExpression;
+import org.drools.spi.Tuple;
+
+public class FieldConstraintTest extends TestCase {
+
+    ClassFieldExtractorCache cache = ClassFieldExtractorCache.getInstance();
+    EqualityEvaluatorsDefinition equals = new EqualityEvaluatorsDefinition();
+    ComparableEvaluatorsDefinition comparables = new ComparableEvaluatorsDefinition();
+
+    public FieldConstraintTest() {
+        super();
+    }
+
+    /**
+     * <pre>
+     *        
+     *         
+     *                ( Cheese (type &quot;cheddar&quot;) )
+     *          
+     *         
+     * </pre>
+     * 
+     * This is currently the same as using a ReturnValueConstraint just that it
+     * doesn't need any requiredDeclarations
+     * 
+     * @throws IntrospectionException
+     */
+    public void testLiteralConstraint() throws IntrospectionException {
+        final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        final InternalWorkingMemory workingMemory = (InternalWorkingMemory) ruleBase.newStatefulSession();
+
+        final ClassFieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                                  "type",
+                                                                  getClass().getClassLoader() );
+
+        final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
+
+        final Evaluator evaluator = equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL );
+
+        final LiteralConstraint constraint = new LiteralConstraint( extractor,
+                                                                    evaluator,
+                                                                    field );
+
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           5 );
+
+        final InternalFactHandle cheddarHandle = (InternalFactHandle) workingMemory.insert( cheddar );
+
+        // check constraint
+        assertTrue( constraint.isAllowed( cheddarHandle,
+                                          workingMemory ) );
+
+        final Cheese stilton = new Cheese( "stilton",
+                                           5 );
+
+        final InternalFactHandle stiltonHandle = (InternalFactHandle) workingMemory.insert( stilton );
+
+        // check constraint
+        assertFalse( constraint.isAllowed( stiltonHandle,
+                                           workingMemory ) );
+    }
+
+    /**
+     * <pre>
+     *        
+     *         
+     *                Cheese( price == 5 )
+     *          
+     *         
+     * </pre>
+     * 
+     * @throws IntrospectionException
+     */
+    public void testPrimitiveLiteralConstraint() throws IntrospectionException {
+        final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        final InternalWorkingMemory workingMemory = (InternalWorkingMemory) ruleBase.newStatefulSession();
+
+        final ClassFieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                                  "price",
+                                                                  getClass().getClassLoader() );
+
+        final FieldValue field = FieldFactory.getFieldValue( 5 );
+
+        final Evaluator evaluator = equals.getEvaluator( ValueType.PINTEGER_TYPE, Operator.EQUAL );
+
+        final LiteralConstraint constraint = new LiteralConstraint( extractor,
+                                                                    evaluator,
+                                                                    field );
+
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           5 );
+
+        final InternalFactHandle cheddarHandle = (InternalFactHandle) workingMemory.insert( cheddar );
+
+        // check constraint
+        assertTrue( constraint.isAllowed( cheddarHandle,
+                                          workingMemory ) );
+
+        final Cheese stilton = new Cheese( "stilton",
+                                           10 );
+
+        final InternalFactHandle stiltonHandle = (InternalFactHandle) workingMemory.insert( stilton );
+
+        // check constraint
+        assertFalse( constraint.isAllowed( stiltonHandle,
+                                           workingMemory ) );
+    }
+
+    /**
+     * <pre>
+     *        
+     *         
+     *                (Cheese (price ?price1 ) 
+     *                (Cheese (price ?price2&amp;:(= ?price2 (* 2 ?price1) )
+     *          
+     *         
+     * </pre>
+     * 
+     * @throws IntrospectionException
+     */
+    public void testPredicateConstraint() throws IntrospectionException {
+        final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        final InternalWorkingMemory workingMemory = (InternalWorkingMemory) ruleBase.newStatefulSession();
+
+        final FieldExtractor priceExtractor = cache.getExtractor( Cheese.class,
+                                                                  "price",
+                                                                  getClass().getClassLoader() );
+
+        Pattern pattern = new Pattern( 0,
+                                       new ClassObjectType( Cheese.class ) );
+
+        // Bind the extractor to a decleration
+        // Declarations know the pattern they derive their value form
+        final Declaration price1Declaration = new Declaration( "price1",
+                                                               priceExtractor,
+                                                               pattern );
+
+        pattern = new Pattern( 1,
+                               new ClassObjectType( Cheese.class ) );
+
+        // Bind the extractor to a decleration
+        // Declarations know the pattern they derive their value form
+        final Declaration price2Declaration = new Declaration( "price2",
+                                                               priceExtractor,
+                                                               pattern );
+
+        final PredicateExpression evaluator = new PredicateExpression() {
+
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public boolean evaluate(Object object,
+                                    Tuple tuple,
+                                    Declaration[] previousDeclarations,
+                                    Declaration[] localDeclarations,
+                                    WorkingMemory workingMemory) {
+                int price1 = previousDeclarations[0].getIntValue( (InternalWorkingMemory) workingMemory,
+                                                                  workingMemory.getObject( tuple.get( previousDeclarations[0] ) ) );
+                int price2 = localDeclarations[0].getIntValue( (InternalWorkingMemory) workingMemory,
+                                                               object );
+
+                return (price2 == (price1 * 2));
+
+            }
+        };
+
+        final PredicateConstraint constraint1 = new PredicateConstraint( evaluator,
+                                                                         new Declaration[]{price1Declaration},
+                                                                         new Declaration[]{price2Declaration},
+                                                                         new String[]{} );
+
+        final Cheese cheddar0 = new Cheese( "cheddar",
+                                            5 );
+        final FactHandle f0 = workingMemory.insert( cheddar0 );
+        InstrumentedReteTuple tuple = new InstrumentedReteTuple( f0 );
+
+        final Cheese cheddar1 = new Cheese( "cheddar",
+                                            10 );
+        final InternalFactHandle f1 = (InternalFactHandle) workingMemory.insert( cheddar1 );
+
+        tuple = new InstrumentedReteTuple( tuple,
+                                           f1 );
+
+        final PredicateContextEntry context = (PredicateContextEntry) constraint1.getContextEntry();
+        context.updateFromTuple( workingMemory,
+                                 tuple );
+        assertTrue( constraint1.isAllowedCachedLeft( context,
+                                                     f1 ) );
+    }
+
+    /**
+     * <pre>
+     *        
+     *         
+     *                (Cheese (price ?price ) 
+     *                (Cheese (price =(* 2 ?price) )
+     *                (Cheese (price &gt;(* 2 ?price) )
+     *          
+     *         
+     * </pre>
+     * 
+     * @throws IntrospectionException
+     */
+    public void testReturnValueConstraint() throws IntrospectionException {
+        final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        final InternalWorkingMemory workingMemory = (InternalWorkingMemory) ruleBase.newStatefulSession();
+
+        final FieldExtractor priceExtractor = cache.getExtractor( Cheese.class,
+                                                                  "price",
+                                                                  getClass().getClassLoader() );
+
+        final Pattern pattern = new Pattern( 0,
+                                             new ClassObjectType( Cheese.class ) );
+
+        // Bind the extractor to a decleration
+        // Declarations know the pattern they derive their value form
+        final Declaration priceDeclaration = new Declaration( "price1",
+                                                              priceExtractor,
+                                                              pattern );
+
+        final ReturnValueExpression isDoubleThePrice = new ReturnValueExpression() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 400L;
+
+            public FieldValue evaluate(Object object,
+                                       Tuple tuple, // ?price
+                                       Declaration[] previousDeclarations,
+                                       Declaration[] localDeclarations,
+                                       WorkingMemory workingMemory) {
+                int price = ((Number) previousDeclarations[0].getValue( (InternalWorkingMemory) workingMemory,
+                                                                        workingMemory.getObject( tuple.get( previousDeclarations[0] ) ) )).intValue();
+                return FieldFactory.getFieldValue( 2 * price );
+
+            }
+        };
+
+        final ReturnValueRestriction restriction1 = new ReturnValueRestriction( priceExtractor,
+                                                                                isDoubleThePrice,
+                                                                                new Declaration[]{priceDeclaration},
+                                                                                new Declaration[0],
+                                                                                new String[0],
+                                                                                equals.getEvaluator( ValueType.INTEGER_TYPE, Operator.EQUAL ) );
+
+        final ReturnValueConstraint constraint1 = new ReturnValueConstraint( priceExtractor,
+                                                                             restriction1 );
+
+        final ReturnValueRestriction restriction2 = new ReturnValueRestriction( priceExtractor,
+                                                                                isDoubleThePrice,
+                                                                                new Declaration[]{priceDeclaration},
+                                                                                new Declaration[0],
+                                                                                new String[0],
+                                                                                comparables.getEvaluator( ValueType.INTEGER_TYPE, Operator.GREATER ) );
+
+        final ReturnValueConstraint constraint2 = new ReturnValueConstraint( priceExtractor,
+                                                                             restriction2 );
+
+        final Cheese cheddar0 = new Cheese( "cheddar",
+                                            5 );
+        final FactHandle f0 = workingMemory.insert( cheddar0 );
+
+        InstrumentedReteTuple tuple = new InstrumentedReteTuple( f0 );
+
+        final Cheese cheddar1 = new Cheese( "cheddar",
+                                            10 );
+        final InternalFactHandle f1 = (InternalFactHandle) workingMemory.insert( cheddar1 );
+        tuple = new InstrumentedReteTuple( tuple,
+                                           f1 );
+
+        final ReturnValueContextEntry context1 = (ReturnValueContextEntry) constraint1.getContextEntry();
+        context1.updateFromTuple( workingMemory,
+                                  tuple );
+        assertTrue( constraint1.isAllowedCachedLeft( context1,
+                                                     f1 ) );
+
+        final ReturnValueContextEntry context2 = (ReturnValueContextEntry) constraint2.getContextEntry();
+        context2.updateFromTuple( workingMemory,
+                                  tuple );
+        assertFalse( constraint2.isAllowedCachedLeft( context2,
+                                                      f1 ) );
+
+        final Cheese cheddar2 = new Cheese( "cheddar",
+                                            11 );
+
+        final InternalFactHandle f2 = (InternalFactHandle) workingMemory.insert( cheddar2 );
+
+        assertTrue( constraint2.isAllowedCachedLeft( context2,
+                                                     f2 ) );
+    }
+
+    /**
+     * <pre>
+     *        
+     *         
+     *                type == &quot;cheddar&quot &amp;&amp; price &gt; 10 
+     *          
+     *         
+     * </pre>
+     * 
+     * Test the use of the composite AND constraint. Composite AND constraints are only
+     * used when nested inside other field constraints, as the top level AND is implicit
+     * 
+     * @throws IntrospectionException
+     */
+    public void testCompositeAndConstraint() {
+        final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        final InternalWorkingMemory workingMemory = (InternalWorkingMemory) ruleBase.newStatefulSession();
+
+        final ClassFieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                                  "type",
+                                                                  getClass().getClassLoader() );
+
+        final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
+
+        final Evaluator evaluator = equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL );
+
+        final LiteralConstraint constraint1 = new LiteralConstraint( extractor,
+                                                                     evaluator,
+                                                                     field );
+
+        final ClassFieldExtractor priceExtractor = cache.getExtractor( Cheese.class,
+                                                                       "price",
+                                                                       getClass().getClassLoader() );
+
+        final FieldValue priceField = FieldFactory.getFieldValue( 10 );
+
+        final Evaluator priceEvaluator = comparables.getEvaluator( ValueType.INTEGER_TYPE, Operator.GREATER );
+
+        final LiteralConstraint constraint2 = new LiteralConstraint( priceExtractor,
+                                                                     priceEvaluator,
+                                                                     priceField );
+
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           15 );
+
+        final AndConstraint constraint = new AndConstraint();
+        constraint.addAlphaConstraint( constraint1 );
+        constraint.addAlphaConstraint( constraint2 );
+
+        final InternalFactHandle cheddarHandle = (InternalFactHandle) workingMemory.insert( cheddar );
+
+        // check constraint
+        assertTrue( constraint.isAllowed( cheddarHandle,
+                                          workingMemory ) );
+
+        cheddar.setPrice( 5 );
+        ((ShadowProxy) cheddarHandle.getObject()).updateProxy();
+        assertFalse( constraint.isAllowed( cheddarHandle,
+                                           workingMemory ) );
+
+        cheddar.setType( "stilton" );
+        ((ShadowProxy) cheddarHandle.getObject()).updateProxy();
+        assertFalse( constraint.isAllowed( cheddarHandle,
+                                           workingMemory ) );
+
+        cheddar.setPrice( 15 );
+        ((ShadowProxy) cheddarHandle.getObject()).updateProxy();
+        assertFalse( constraint.isAllowed( cheddarHandle,
+                                           workingMemory ) );
+    }
+
+    /**
+     * <pre>
+     *        
+     *         
+     *                Cheese( type == &quot;cheddar&quot || price &gt; 10 ) 
+     *          
+     *         
+     * </pre>
+     * 
+     * Test the use of the composite OR constraint. 
+     * 
+     * @throws IntrospectionException
+     */
+    public void testCompositeOrConstraint() {
+        final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        final InternalWorkingMemory workingMemory = (InternalWorkingMemory) ruleBase.newStatefulSession();
+
+        final ClassFieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                                  "type",
+                                                                  getClass().getClassLoader() );
+
+        final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
+
+        final Evaluator evaluator = equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL );
+
+        final LiteralConstraint constraint1 = new LiteralConstraint( extractor,
+                                                                     evaluator,
+                                                                     field );
+
+        final ClassFieldExtractor priceExtractor = cache.getExtractor( Cheese.class,
+                                                                       "price",
+                                                                       getClass().getClassLoader() );
+
+        final FieldValue priceField = FieldFactory.getFieldValue( 10 );
+
+        final Evaluator priceEvaluator = comparables.getEvaluator( ValueType.INTEGER_TYPE, Operator.GREATER );
+
+        final LiteralConstraint constraint2 = new LiteralConstraint( priceExtractor,
+                                                                     priceEvaluator,
+                                                                     priceField );
+
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           15 );
+
+        final OrConstraint constraint = new OrConstraint();
+        constraint.addAlphaConstraint( constraint1 );
+        constraint.addAlphaConstraint( constraint2 );
+
+        final InternalFactHandle cheddarHandle = (InternalFactHandle) workingMemory.insert( cheddar );
+
+        // check constraint
+        assertTrue( constraint.isAllowed( cheddarHandle,
+                                          workingMemory ) );
+
+        cheddar.setPrice( 5 );
+        ((ShadowProxy) cheddarHandle.getObject()).updateProxy();
+        assertTrue( constraint.isAllowed( cheddarHandle,
+                                          workingMemory ) );
+
+        cheddar.setType( "stilton" );
+        ((ShadowProxy) cheddarHandle.getObject()).updateProxy();
+        assertFalse( constraint.isAllowed( cheddarHandle,
+                                           workingMemory ) );
+
+        cheddar.setPrice( 15 );
+        ((ShadowProxy) cheddarHandle.getObject()).updateProxy();
+        assertTrue( constraint.isAllowed( cheddarHandle,
+                                          workingMemory ) );
+    }
+
+    /**
+     * <pre>
+     *        
+     *         
+     *                Cheese( ( type == &quot;cheddar&quot &amp;&amp; price &gt; 10) || ( type == &quote;stilton&quote; && price &lt; 10 ) ) 
+     *          
+     *         
+     * </pre>
+     * 
+     * Test the use of the composite OR constraint. 
+     * 
+     * @throws IntrospectionException
+     */
+    public void testNestedCompositeConstraints() {
+        final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        final InternalWorkingMemory workingMemory = (InternalWorkingMemory) ruleBase.newStatefulSession();
+
+        final ClassFieldExtractor typeExtractor = cache.getExtractor( Cheese.class,
+                                                                      "type",
+                                                                      getClass().getClassLoader() );
+
+        final FieldValue cheddarField = FieldFactory.getFieldValue( "cheddar" );
+
+        final Evaluator stringEqual = equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL );
+
+        // type == 'cheddar'
+        final LiteralConstraint constraint1 = new LiteralConstraint( typeExtractor,
+                                                                     stringEqual,
+                                                                     cheddarField );
+
+        final ClassFieldExtractor priceExtractor = cache.getExtractor( Cheese.class,
+                                                                       "price",
+                                                                       getClass().getClassLoader() );
+
+        final FieldValue field10 = FieldFactory.getFieldValue( 10 );
+
+        final Evaluator integerGreater =  comparables.getEvaluator( ValueType.INTEGER_TYPE, Operator.GREATER );
+
+        // price > 10
+        final LiteralConstraint constraint2 = new LiteralConstraint( priceExtractor,
+                                                                     integerGreater,
+                                                                     field10 );
+
+        // type == 'cheddar' && price > 10
+        final AndConstraint and1 = new AndConstraint();
+        and1.addAlphaConstraint( constraint1 );
+        and1.addAlphaConstraint( constraint2 );
+
+        final FieldValue stiltonField = FieldFactory.getFieldValue( "stilton" );
+        // type == 'stilton'
+        final LiteralConstraint constraint3 = new LiteralConstraint( typeExtractor,
+                                                                     stringEqual,
+                                                                     stiltonField );
+
+        final Evaluator integerLess =  comparables.getEvaluator( ValueType.INTEGER_TYPE, Operator.LESS );
+
+        // price < 10
+        final LiteralConstraint constraint4 = new LiteralConstraint( priceExtractor,
+                                                                     integerLess,
+                                                                     field10 );
+
+        // type == 'stilton' && price < 10
+        final AndConstraint and2 = new AndConstraint();
+        and2.addAlphaConstraint( constraint3 );
+        and2.addAlphaConstraint( constraint4 );
+
+        // ( type == 'cheddar' && price > 10 ) || ( type == 'stilton' && price < 10 )
+        final OrConstraint constraint = new OrConstraint();
+        constraint.addAlphaConstraint( and1 );
+        constraint.addAlphaConstraint( and2 );
+
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           15 );
+
+        final InternalFactHandle cheddarHandle = (InternalFactHandle) workingMemory.insert( cheddar );
+
+        // check constraint
+        assertTrue( constraint.isAllowed( cheddarHandle,
+                                          workingMemory ) );
+
+        cheddar.setPrice( 5 );
+        ((ShadowProxy) cheddarHandle.getObject()).updateProxy();
+        assertFalse( constraint.isAllowed( cheddarHandle,
+                                           workingMemory ) );
+
+        cheddar.setType( "stilton" );
+        ((ShadowProxy) cheddarHandle.getObject()).updateProxy();
+        assertTrue( constraint.isAllowed( cheddarHandle,
+                                          workingMemory ) );
+
+        cheddar.setPrice( 15 );
+        ((ShadowProxy) cheddarHandle.getObject()).updateProxy();
+        assertFalse( constraint.isAllowed( cheddarHandle,
+                                           workingMemory ) );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/FixedDurationTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/FixedDurationTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/FixedDurationTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,65 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import junit.framework.TestCase;
+
+public class FixedDurationTest extends TestCase {
+    public void testConstruct() throws Exception {
+        FixedDuration dur = new FixedDuration();
+
+        assertEquals( 0,
+                      dur.getDuration( null ) );
+
+        dur = new FixedDuration( 42000 );
+
+        assertEquals( 42000,
+                      dur.getDuration( null ) );
+    }
+
+    public void testAdd() throws Exception {
+        final FixedDuration dur = new FixedDuration();
+
+        assertEquals( 0,
+                      dur.getDuration( null ) );
+
+        dur.addSeconds( 42 );
+
+        assertEquals( 42000,
+                      dur.getDuration( null ) );
+
+        dur.addMinutes( 2 );
+
+        assertEquals( 162000,
+                      dur.getDuration( null ) );
+
+        dur.addHours( 2 );
+
+        assertEquals( 7362000,
+                      dur.getDuration( null ) );
+
+        dur.addDays( 2 );
+
+        assertEquals( 180162000,
+                      dur.getDuration( null ) );
+
+        dur.addWeeks( 2 );
+
+        assertEquals( 1389762000,
+                      dur.getDuration( null ) );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/GroupElementTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/GroupElementTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/GroupElementTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,337 @@
+package org.drools.rule;
+
+import org.drools.RuntimeDroolsException;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+public class GroupElementTest extends TestCase {
+
+    public void testPackNestedAnd() {
+        final GroupElement and1 = GroupElementFactory.newAndInstance();
+        final Pattern pattern1 = new Pattern( 0,
+                                     null );
+        and1.addChild( pattern1 );
+
+        final Pattern pattern2 = new Pattern( 0,
+                                     null );
+        and1.addChild( pattern2 );
+
+        assertEquals( 2,
+                      and1.getChildren().size() );
+        assertSame( pattern1,
+                    and1.getChildren().get( 0 ) );
+        assertSame( pattern2,
+                    and1.getChildren().get( 1 ) );
+
+        final GroupElement and2 = GroupElementFactory.newAndInstance();
+        and2.addChild( and1 );
+
+        and2.pack();
+        assertEquals( 2,
+                      and2.getChildren().size() );
+        assertSame( pattern1,
+                    and2.getChildren().get( 0 ) );
+        assertSame( pattern2,
+                    and2.getChildren().get( 1 ) );
+    }
+
+    public void testPackNestedOr() {
+        final GroupElement or1 = GroupElementFactory.newOrInstance();
+        final Pattern pattern1 = new Pattern( 0,
+                                     null );
+        or1.addChild( pattern1 );
+
+        final Pattern pattern2 = new Pattern( 0,
+                                     null );
+        or1.addChild( pattern2 );
+
+        assertEquals( 2,
+                      or1.getChildren().size() );
+        assertSame( pattern1,
+                    or1.getChildren().get( 0 ) );
+        assertSame( pattern2,
+                    or1.getChildren().get( 1 ) );
+
+        final GroupElement or2 = GroupElementFactory.newOrInstance();
+        or2.addChild( or1 );
+
+        or2.pack();
+
+        assertEquals( 2,
+                      or2.getChildren().size() );
+        assertSame( pattern1,
+                    or2.getChildren().get( 0 ) );
+        assertSame( pattern2,
+                    or2.getChildren().get( 1 ) );
+    }
+
+    public void testPackNestedExists() {
+        final GroupElement exists1 = GroupElementFactory.newExistsInstance();
+        final Pattern pattern1 = new Pattern( 0,
+                                     null );
+        exists1.addChild( pattern1 );
+
+        assertEquals( 1,
+                      exists1.getChildren().size() );
+        assertSame( pattern1,
+                    exists1.getChildren().get( 0 ) );
+
+        final GroupElement exists2 = GroupElementFactory.newExistsInstance();
+        exists2.addChild( exists1 );
+
+        exists2.pack();
+
+        assertEquals( 1,
+                      exists2.getChildren().size() );
+        assertSame( pattern1,
+                    exists2.getChildren().get( 0 ) );
+    }
+
+    public void testAddMultipleChildsIntoNot() {
+        final GroupElement not = GroupElementFactory.newNotInstance();
+
+        final Pattern pattern1 = new Pattern( 0,
+                                     null );
+        try {
+            not.addChild( pattern1 );
+        } catch ( final RuntimeDroolsException rde ) {
+            Assert.fail( "Adding a single child is not supposed to throw Exception for NOT GE: " + rde.getMessage() );
+        }
+
+        final Pattern pattern2 = new Pattern( 0,
+                                     null );
+        try {
+            not.addChild( pattern2 );
+            Assert.fail( "Adding a second child into a NOT GE should throw Exception" );
+        } catch ( final RuntimeDroolsException rde ) {
+            // everything is fine
+        }
+    }
+
+    public void testAddSingleBranchAnd() {
+        final GroupElement and1 = GroupElementFactory.newAndInstance();
+        final Pattern pattern = new Pattern( 0,
+                                    null );
+        and1.addChild( pattern );
+        assertEquals( 1,
+                      and1.getChildren().size() );
+        assertSame( pattern,
+                    and1.getChildren().get( 0 ) );
+
+        final GroupElement or1 = GroupElementFactory.newOrInstance();
+        or1.addChild( and1 );
+
+        or1.pack();
+        assertEquals( 1,
+                      or1.getChildren().size() );
+        assertSame( pattern,
+                    or1.getChildren().get( 0 ) );
+    }
+
+    public void testAddSingleBranchOr() {
+        final GroupElement or1 = GroupElementFactory.newOrInstance();
+        final Pattern pattern = new Pattern( 0,
+                                    null );
+        or1.addChild( pattern );
+        assertEquals( 1,
+                      or1.getChildren().size() );
+        assertSame( pattern,
+                    or1.getChildren().get( 0 ) );
+
+        final GroupElement and1 = GroupElementFactory.newAndInstance();
+        and1.addChild( or1 );
+
+        and1.pack();
+        assertEquals( 1,
+                      and1.getChildren().size() );
+        assertSame( pattern,
+                    and1.getChildren().get( 0 ) );
+    }
+
+    /**
+     * This test tests deep nested structures, and shall transform this:
+     * 
+     *    AND2
+     *     |
+     *    OR3
+     *     |
+     *    OR2
+     *     |
+     *    AND1
+     *     |
+     *    OR1
+     *    / \
+     *   C1  C2
+     *   
+     * Into this:
+     * 
+     *   OR1
+     *   / \
+     *  C1 C2
+     *
+     */
+    public void testDeepNestedStructure() {
+        final GroupElement or1 = GroupElementFactory.newOrInstance();
+        final Pattern pattern1 = new Pattern( 0,
+                                     null );
+        or1.addChild( pattern1 );
+
+        final Pattern pattern2 = new Pattern( 0,
+                                     null );
+        or1.addChild( pattern2 );
+
+        final GroupElement and1 = GroupElementFactory.newAndInstance();
+        and1.addChild( or1 );
+        assertEquals( 1,
+                      and1.getChildren().size() );
+        assertSame( or1,
+                    and1.getChildren().get( 0 ) );
+
+        assertSame( pattern1,
+                    or1.getChildren().get( 0 ) );
+        assertSame( pattern2,
+                    or1.getChildren().get( 1 ) );
+
+        final GroupElement or2 = GroupElementFactory.newOrInstance();
+        or2.addChild( and1 );
+
+        assertEquals( 1,
+                      or2.getChildren().size() );
+        assertSame( and1,
+                    or2.getChildren().get( 0 ) );
+
+        final GroupElement or3 = GroupElementFactory.newOrInstance();
+        or3.addChild( or2 );
+
+        assertEquals( 1,
+                      or2.getChildren().size() );
+        assertSame( or2,
+                    or3.getChildren().get( 0 ) );
+
+        final GroupElement and2 = GroupElementFactory.newAndInstance();
+        and2.addChild( or3 );
+
+        assertEquals( 1,
+                      and2.getChildren().size() );
+        assertSame( or3,
+                    and2.getChildren().get( 0 ) );
+
+        // Now pack the structure
+        and2.pack();
+
+        // and2 now is in fact transformed into an OR
+        assertEquals( GroupElement.OR,
+                      and2.getType() );
+
+        assertEquals( 2,
+                      and2.getChildren().size() );
+
+        assertSame( pattern1,
+                    and2.getChildren().get( 0 ) );
+        assertSame( pattern2,
+                    and2.getChildren().get( 1 ) );
+
+    }
+
+    /**
+     * This test tests deep nested structures, and shall transform this:
+     * 
+     *      AND2
+     *      / \ 
+     *    OR3  C3
+     *     |
+     *    OR2
+     *     |
+     *    AND1
+     *     |
+     *    OR1
+     *    / \
+     *   C1  C2
+     *   
+     * Into this:
+     * 
+     *     AND2
+     *     /  \
+     *   OR1  C3
+     *   / \
+     *  C1 C2
+     *
+     */
+    public void testDeepNestedStructureWithMultipleElementsInRoot() {
+        final GroupElement or1 = GroupElementFactory.newOrInstance();
+        final Pattern pattern1 = new Pattern( 0,
+                                     null );
+        or1.addChild( pattern1 );
+
+        final Pattern pattern2 = new Pattern( 0,
+                                     null );
+        or1.addChild( pattern2 );
+
+        final GroupElement and1 = GroupElementFactory.newAndInstance();
+        and1.addChild( or1 );
+        assertEquals( 1,
+                      and1.getChildren().size() );
+        assertSame( or1,
+                    and1.getChildren().get( 0 ) );
+
+        assertSame( pattern1,
+                    or1.getChildren().get( 0 ) );
+        assertSame( pattern2,
+                    or1.getChildren().get( 1 ) );
+
+        final GroupElement or2 = GroupElementFactory.newOrInstance();
+        or2.addChild( and1 );
+
+        assertEquals( 1,
+                      or2.getChildren().size() );
+        assertSame( and1,
+                    or2.getChildren().get( 0 ) );
+
+        final GroupElement or3 = GroupElementFactory.newOrInstance();
+        or3.addChild( or2 );
+
+        assertEquals( 1,
+                      or2.getChildren().size() );
+        assertSame( or2,
+                    or3.getChildren().get( 0 ) );
+
+        final GroupElement and2 = GroupElementFactory.newAndInstance();
+        and2.addChild( or3 );
+
+        final Pattern pattern3 = new Pattern( 0,
+                                     null );
+        and2.addChild( pattern3 );
+
+        assertEquals( 2,
+                      and2.getChildren().size() );
+        assertSame( or3,
+                    and2.getChildren().get( 0 ) );
+        assertSame( pattern3,
+                    and2.getChildren().get( 1 ) );
+
+        // Now pack the structure
+        and2.pack();
+
+        // and2 now is in fact transformed into an OR
+        assertTrue( and2.isAnd() );
+
+        assertEquals( 2,
+                      and2.getChildren().size() );
+
+        // order must be the same
+        assertSame( or1,
+                    and2.getChildren().get( 0 ) );
+        assertSame( pattern3,
+                    and2.getChildren().get( 1 ) );
+
+        assertEquals( 2,
+                      or1.getChildren().size() );
+        assertSame( pattern1,
+                    or1.getChildren().get( 0 ) );
+        assertSame( pattern2,
+                    or1.getChildren().get( 1 ) );
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/LogicTransformerTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/LogicTransformerTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/LogicTransformerTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,729 @@
+package org.drools.rule;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.drools.DroolsTestCase;
+import org.drools.base.ClassObjectType;
+import org.drools.spi.ObjectType;
+
+public class LogicTransformerTest extends DroolsTestCase {
+    /**
+     * (a||b)&&c
+     * 
+     * <pre>
+     *               and
+     *               / \
+     *              or  c 
+     *             /  \
+     *            a    b
+     * </pre>
+     * 
+     * Should become (a&&c)||(b&&c)
+     * 
+     * <pre>
+     *                 
+     *               or
+     *              /  \  
+     *             /    \ 
+     *            /      \ 
+     *             and      and     
+     *          / \      / \
+     *         a   c    b   c
+     * </pre>
+     */
+    public void testSingleOrAndOrTransformation() throws InvalidPatternException {
+        final ObjectType type = new ClassObjectType( String.class );
+        final Pattern a = new Pattern( 0,
+                                     type,
+                                     "a" );
+        final Pattern b = new Pattern( 1,
+                                     type,
+                                     "b" );
+        final Pattern c = new Pattern( 2,
+                                     type,
+                                     "c" );
+
+        final GroupElement or = GroupElementFactory.newOrInstance();
+        or.addChild( a );
+        or.addChild( b );
+
+        final GroupElement parent = GroupElementFactory.newAndInstance();
+        parent.addChild( or );
+        parent.addChild( c );
+
+        LogicTransformer.getInstance().applyOrTransformation( parent );
+
+        assertLength( 2,
+                      parent.getChildren() );
+        assertEquals( GroupElement.class,
+                      parent.getChildren().get( 0 ).getClass() );
+        assertEquals( GroupElement.class,
+                      parent.getChildren().get( 1 ).getClass() );
+
+        final GroupElement and1 = (GroupElement) parent.getChildren().get( 0 );
+        assertTrue( and1.isAnd() );
+
+        // transformation MUST keep the order
+        assertEquals( a,
+                      and1.getChildren().get( 0 ) );
+        assertEquals( c,
+                      and1.getChildren().get( 1 ) );
+
+        final GroupElement and2 = (GroupElement) parent.getChildren().get( 1 );
+        assertEquals( b,
+                      and2.getChildren().get( 0 ) );
+        assertEquals( c,
+                      and2.getChildren().get( 1 ) );
+
+    }
+
+    /**
+     * (a||b)&&c
+     * 
+     * <pre>
+     *                   And
+     *                  /|\ \__
+     *                _/ | \_  \_
+     *               /   |   \   \  
+     *              or   |   or   not
+     *             /   \ |  / \    |
+     *            a    b c d   e   f
+     * </pre>
+     * 
+     * Should become (a&&c)||(b&&c)
+     * 
+     * <pre>
+     *                           /\
+     *                         _/  \_
+     *                        /      \
+     *                      _/|       |\_
+     *                   __/  |       |  \__
+     *                __/     |       |     \__
+     *               /        |       |        \
+     *              and      and     and      and
+     *             /||\     /||\     /||\     /||\
+     *            a cd Not a ce Not b cd Not b ce Not
+     *                  |        |        |        |
+     *                  f        f        f        f
+     * </pre>
+     */
+    public void testMultipleOrAndOrTransformation() throws InvalidPatternException {
+        final ObjectType type = new ClassObjectType( String.class );
+        final Pattern a = new Pattern( 0,
+                                     type,
+                                     "a" );
+        final Pattern b = new Pattern( 1,
+                                     type,
+                                     "b" );
+        final Pattern c = new Pattern( 2,
+                                     type,
+                                     "c" );
+        final Pattern d = new Pattern( 3,
+                                     type,
+                                     "d" );
+        final Pattern e = new Pattern( 4,
+                                     type,
+                                     "e" );
+        final Pattern f = new Pattern( 5,
+                                     type,
+                                     "f" );
+
+        final GroupElement parent = GroupElementFactory.newAndInstance();
+        final GroupElement or = GroupElementFactory.newOrInstance();
+        or.addChild( a );
+        or.addChild( b );
+        parent.addChild( or );
+        parent.addChild( c );
+
+        final GroupElement or2 = GroupElementFactory.newOrInstance();
+
+        or2.addChild( d );
+        or2.addChild( e );
+        parent.addChild( or2 );
+
+        final GroupElement not = GroupElementFactory.newNotInstance();
+        not.addChild( f );
+        parent.addChild( not );
+
+        LogicTransformer.getInstance().applyOrTransformation( parent );
+
+        assertEquals( GroupElement.OR,
+                      parent.getType() );
+
+        assertLength( 4,
+                      parent.getChildren() );
+        assertEquals( GroupElement.class,
+                      parent.getChildren().get( 0 ).getClass() );
+        assertEquals( GroupElement.class,
+                      parent.getChildren().get( 1 ).getClass() );
+        assertEquals( GroupElement.class,
+                      parent.getChildren().get( 2 ).getClass() );
+        assertEquals( GroupElement.class,
+                      parent.getChildren().get( 3 ).getClass() );
+
+        GroupElement and1 = (GroupElement) parent.getChildren().get( 0 );
+        assertTrue( and1.isAnd() );
+        assertLength( 4,
+                      and1.getChildren() );
+        assertEquals( a,
+                      and1.getChildren().get( 0 ) );
+        assertEquals( c,
+                      and1.getChildren().get( 1 ) );
+        assertEquals( d,
+                      and1.getChildren().get( 2 ) );
+        assertEquals( not,
+                      and1.getChildren().get( 3 ) );
+
+        and1 = (GroupElement) parent.getChildren().get( 1 );
+        assertTrue( and1.isAnd() );
+        assertLength( 4,
+                      and1.getChildren() );
+        assertEquals( a,
+                      and1.getChildren().get( 0 ) );
+        assertEquals( c,
+                      and1.getChildren().get( 1 ) );
+        assertEquals( e,
+                      and1.getChildren().get( 2 ) );
+        assertEquals( not,
+                      and1.getChildren().get( 3 ) );
+
+        and1 = (GroupElement) parent.getChildren().get( 2 );
+        assertTrue( and1.isAnd() );
+        assertLength( 4,
+                      and1.getChildren() );
+        assertEquals( b,
+                      and1.getChildren().get( 0 ) );
+        assertEquals( c,
+                      and1.getChildren().get( 1 ) );
+        assertEquals( d,
+                      and1.getChildren().get( 2 ) );
+        assertEquals( not,
+                      and1.getChildren().get( 3 ) );
+
+        and1 = (GroupElement) parent.getChildren().get( 3 );
+        assertTrue( and1.isAnd() );
+        assertLength( 4,
+                      and1.getChildren() );
+        assertEquals( b,
+                      and1.getChildren().get( 0 ) );
+        assertEquals( c,
+                      and1.getChildren().get( 1 ) );
+        assertEquals( e,
+                      and1.getChildren().get( 2 ) );
+        assertEquals( not,
+                      and1.getChildren().get( 3 ) );
+
+    }
+
+    /**
+     * This data structure is now valid
+     * 
+     * (Not (OR (A B) ) )
+     * 
+     * <pre>
+     *             Not
+     *              | 
+     *             or   
+     *            /  \
+     *           a    b
+     * </pre>
+     * 
+     * Should become:
+     * 
+     * <pre>
+     *             And
+     *             / \ 
+     *           Not Not   
+     *            |   |
+     *            a   b
+     * </pre>
+     * 
+     * 
+     */
+    public void testNotOrTransformation() throws InvalidPatternException {
+        final ObjectType type = new ClassObjectType( String.class );
+        final Pattern a = new Pattern( 0,
+                                     type,
+                                     "a" );
+        final Pattern b = new Pattern( 1,
+                                     type,
+                                     "b" );
+
+        final GroupElement parent = GroupElementFactory.newNotInstance();
+        final GroupElement or = GroupElementFactory.newOrInstance();
+        parent.addChild( or );
+
+        or.addChild( a );
+        or.addChild( b );
+
+        LogicTransformer.getInstance().applyOrTransformation( parent );
+
+        assertTrue( parent.isAnd() );
+        assertEquals( 2,
+                      parent.getChildren().size() );
+
+        // we must ensure order
+        final GroupElement b1 = (GroupElement) parent.getChildren().get( 0 );
+        final GroupElement b2 = (GroupElement) parent.getChildren().get( 1 );
+        assertTrue( b1.isNot() );
+        assertTrue( b2.isNot() );
+
+        assertEquals( 1,
+                      b1.getChildren().size() );
+        assertEquals( a,
+                      b1.getChildren().get( 0 ) );
+
+        assertEquals( 1,
+                      b2.getChildren().size() );
+        assertEquals( b,
+                      b2.getChildren().get( 0 ) );
+    }
+
+    /**
+     * This data structure is now valid (Exists (OR (A B) ) )
+     * 
+     * <pre>
+     *             Exists
+     *              | 
+     *             or   
+     *            /  \
+     *           a    b
+     * </pre>
+     * 
+     * Should become:
+     * 
+     * <pre>
+     *              Or
+     *             /  \ 
+     *        Exists  Exists   
+     *            |    |
+     *            a    b
+     * </pre>
+     */
+    public void testExistOrTransformation() throws InvalidPatternException {
+        final ObjectType type = new ClassObjectType( String.class );
+        final Pattern a = new Pattern( 0,
+                                     type,
+                                     "a" );
+        final Pattern b = new Pattern( 1,
+                                     type,
+                                     "b" );
+
+        final GroupElement parent = GroupElementFactory.newExistsInstance();
+        final GroupElement or = GroupElementFactory.newOrInstance();
+        parent.addChild( or );
+
+        or.addChild( a );
+        or.addChild( b );
+
+        LogicTransformer.getInstance().applyOrTransformation( parent );
+
+        assertTrue( parent.isOr() );
+        assertEquals( 2,
+                      parent.getChildren().size() );
+
+        // we must ensure order
+        final GroupElement b1 = (GroupElement) parent.getChildren().get( 0 );
+        final GroupElement b2 = (GroupElement) parent.getChildren().get( 1 );
+        assertTrue( b1.isExists() );
+        assertTrue( b2.isExists() );
+
+        assertEquals( 1,
+                      b1.getChildren().size() );
+        assertEquals( a,
+                      b1.getChildren().get( 0 ) );
+
+        assertEquals( 1,
+                      b2.getChildren().size() );
+        assertEquals( b,
+                      b2.getChildren().get( 0 ) );
+
+    }
+
+    public void testEliminateEmptyBranchesAndDuplications() throws InvalidRuleException {
+        final ObjectType type = new ClassObjectType( String.class );
+        final Pattern a = new Pattern( 0,
+                                     type,
+                                     "a" );
+        final Pattern b = new Pattern( 1,
+                                     type,
+                                     "b" );
+        final Pattern c = new Pattern( 2,
+                                     type,
+                                     "c" );
+        final Pattern d = new Pattern( 3,
+                                     type,
+                                     "d" );
+
+        final GroupElement and1 = GroupElementFactory.newAndInstance();
+        and1.addChild( a );
+        and1.addChild( b );
+
+        final GroupElement and2 = GroupElementFactory.newAndInstance();
+        and2.addChild( c );
+        and2.addChild( d );
+
+        and1.addChild( and2 );
+
+        final GroupElement or = GroupElementFactory.newOrInstance();
+        and1.addChild( or );
+
+        final GroupElement[] result = LogicTransformer.getInstance().transform( and1 );
+
+        assertLength( 1,
+                      result );
+        assertLength( 4,
+                      result[0].getChildren() );
+        // we must ensure order
+        assertEquals( a,
+                      result[0].getChildren().get( 0 ) );
+        assertEquals( b,
+                      result[0].getChildren().get( 1 ) );
+        assertEquals( c,
+                      result[0].getChildren().get( 2 ) );
+        assertEquals( d,
+                      result[0].getChildren().get( 3 ) );
+
+    }
+
+    /**
+     * <pre>
+     *                         _/|\_
+     *                      __/  |  \__
+     *                     /     |     \ 
+     *                  __/      |      \__
+     *                 /         |         \
+     *                And       and        Not
+     *               / | \      / \         |
+     *             a  And d    e  Or        i
+     *                / \        /  \      
+     *               b  Not     h  Exists    
+     *                   |           |      
+     *                  Not          g   
+     *                   |           
+     *                   c         
+     * </pre>
+     * 
+     *   It is important to ensure that the order of
+     *   the elements is not changed after transformation
+     * 
+     * <pre>
+     *                            Or 
+     *                           _/ \__
+     *                        __/      \___
+     *                       /             \__
+     *                    __/                 \__
+     *                   /                       \__
+     *                  /                           \__
+     *                 |                               \
+     *                And                             And
+     *            /|  |  | | | \                /|  |  | |   |    \
+     *           a b Not d e h Not             a b Not d e Exists Not
+     *                |         |                   |        |     |
+     *               Not        i                  Not       g     i
+     *                |                             |
+     *                c                             c
+     * </pre>
+     * 
+     * @throws IOException
+     * @throws ClassNotFoundException
+     * 
+     * 
+     * 
+     */
+    public void testProcessTree() throws IOException,
+                                 ClassNotFoundException,
+                                 InvalidPatternException {
+        final ObjectType type = new ClassObjectType( String.class );
+        final Pattern a = new Pattern( 0,
+                                     type,
+                                     "a" );
+        final Pattern b = new Pattern( 1,
+                                     type,
+                                     "b" );
+        final Pattern c = new Pattern( 2,
+                                     type,
+                                     "c" );
+        final Pattern d = new Pattern( 3,
+                                     type,
+                                     "d" );
+        final Pattern e = new Pattern( 4,
+                                     type,
+                                     "e" );
+        final Pattern g = new Pattern( 5,
+                                     type,
+                                     "g" );
+        final Pattern h = new Pattern( 6,
+                                     type,
+                                     "h" );
+        final Pattern i = new Pattern( 7,
+                                     type,
+                                     "i" );
+
+        final GroupElement and1 = GroupElementFactory.newAndInstance();
+        final GroupElement and2 = GroupElementFactory.newAndInstance();
+        and1.addChild( a );
+        and1.addChild( and2 );
+        and2.addChild( b );
+        final GroupElement not1 = GroupElementFactory.newNotInstance();
+        final GroupElement not2 = GroupElementFactory.newNotInstance();
+        not1.addChild( not2 );
+        not2.addChild( c );
+        and2.addChild( not1 );
+        and1.addChild( d );
+
+        final GroupElement and3 = GroupElementFactory.newAndInstance();
+        and3.addChild( e );
+        final GroupElement or1 = GroupElementFactory.newOrInstance();
+        and3.addChild( or1 );
+        final GroupElement exist1 = GroupElementFactory.newExistsInstance();
+        exist1.addChild( g );
+        or1.addChild( h );
+        or1.addChild( exist1 );
+
+        final GroupElement not3 = GroupElementFactory.newNotInstance();
+        not3.addChild( i );
+
+        final GroupElement root = GroupElementFactory.newAndInstance();
+        root.addChild( and1 );
+        root.addChild( and3 );
+        root.addChild( not3 );
+
+        final GroupElement[] result = LogicTransformer.getInstance().transform( root );
+
+        // ----------------------------------------------------------------------------------
+        // Now construct the result tree so we can test root against what it
+        // should look like
+        // ----------------------------------------------------------------------------------
+
+        // Get known correct tree
+        // The binary stream was created from a handchecked correct output
+
+        // Uncomment this when you need to output a new known correct tree
+        // result
+//        writeTree( result,
+//                   "correct_processTree1.dat" );
+        final ObjectInputStream ois = new ObjectInputStream( this.getClass().getResourceAsStream( "/correct_processTree1.dat" ) );
+
+        final GroupElement[] correctResultRoot = (GroupElement[]) ois.readObject();
+
+        // Make sure they are equal
+        for ( int j = 0; j < correctResultRoot.length; j++ ) {
+            assertEquals( correctResultRoot[j],
+                          result[j] );
+        }
+    }
+
+    public void testCloneable() {
+        final ObjectType type = new ClassObjectType( String.class );
+        final Pattern a = new Pattern( 0,
+                                     type,
+                                     "a" );
+        final Pattern b = new Pattern( 1,
+                                     type,
+                                     "b" );
+        final Pattern c = new Pattern( 2,
+                                     type,
+                                     "c" );
+        final Pattern d = new Pattern( 3,
+                                     type,
+                                     "d" );
+        final Pattern e = new Pattern( 4,
+                                     type,
+                                     "e" );
+        final Pattern f = new Pattern( 5,
+                                     type,
+                                     "f" );
+        final Pattern g = new Pattern( 6,
+                                     type,
+                                     "g" );
+        final Pattern h = new Pattern( 7,
+                                     type,
+                                     "h" );
+
+        // Test against a known false tree
+        final GroupElement and = GroupElementFactory.newAndInstance();
+        and.addChild( a );
+        and.addChild( b );
+
+        final GroupElement or = GroupElementFactory.newOrInstance();
+        or.addChild( c );
+        or.addChild( d );
+        and.addChild( or );
+        final GroupElement and2 = GroupElementFactory.newAndInstance();
+        and2.addChild( e );
+        and2.addChild( f );
+        or.addChild( and2 );
+
+        final GroupElement not = GroupElementFactory.newNotInstance();
+        and.addChild( not );
+        final GroupElement or2 = GroupElementFactory.newOrInstance();
+        not.addChild( or2 );
+        or2.addChild( g );
+        or2.addChild( h );
+
+        final GroupElement cloned = (GroupElement) and.clone();
+
+        assertEquals( and,
+                      cloned );
+
+    }
+
+    /**
+     * 
+     * 
+     * /**
+     * 
+     * <pre>
+     *                         _/|\_
+     *                      __/  |  \__
+     *                     /     |     \ 
+     *                  __/      |      \__
+     *                 /         |         \
+     *                And       or         And
+     *               /  \       / \        /  \
+     *             a    Or     d   e      Not OR
+     *                 / \                |  / | 
+     *               b    c               f g Not
+     *                                         |
+     *                                         h
+     *                  
+     *                   
+     *                  
+     * </pre>
+     * 
+     * Each And is a Rete sub rule
+     * 
+     * <pre>
+     *     
+     *    
+     *       And___     And___      And___      And___        And__    And___       And___    And___     
+     *      ||| |  \   ||| |  \     ||| |  \   ||| |  \     ||| |  \  ||| |  \     ||| |  \  ||| |  \ 
+     *      abd Not g  abd Not Not  abe Not g  abe Not Not  acd Not g acd Not Not  ace Not g ace Not Not
+     *           |          |   |        |          |   |        |        |    |       |          |   |   
+     *           f          f   h        f          f   h        f        f    h       f          f   h
+     *                        
+     *                        
+     * </pre>
+     * 
+     * @throws IOException
+     * @throws ClassNotFoundException
+     * 
+     * 
+     * 
+     * 
+     * @throws IOException
+     * @throws ClassNotFoundException
+     * 
+     */
+    public void testTransform() throws IOException,
+                               ClassNotFoundException,
+                               InvalidPatternException {
+        final ObjectType type = new ClassObjectType( String.class );
+        final Pattern a = new Pattern( 0,
+                                     type,
+                                     "a" );
+        final Pattern b = new Pattern( 1,
+                                     type,
+                                     "b" );
+        final Pattern c = new Pattern( 2,
+                                     type,
+                                     "c" );
+        final Pattern d = new Pattern( 3,
+                                     type,
+                                     "d" );
+        final Pattern e = new Pattern( 4,
+                                     type,
+                                     "e" );
+        final Pattern f = new Pattern( 5,
+                                     type,
+                                     "f" );
+        final Pattern g = new Pattern( 6,
+                                     type,
+                                     "g" );
+        final Pattern h = new Pattern( 7,
+                                     type,
+                                     "h" );
+
+        final GroupElement and = GroupElementFactory.newAndInstance();
+
+        final GroupElement and1 = GroupElementFactory.newAndInstance();
+        and1.addChild( a );
+        final GroupElement or1 = GroupElementFactory.newOrInstance();
+        or1.addChild( b );
+        or1.addChild( c );
+        and1.addChild( or1 );
+        and.addChild( and1 );
+
+        final GroupElement or2 = GroupElementFactory.newOrInstance();
+        or2.addChild( d );
+        or2.addChild( e );
+        and.addChild( or2 );
+
+        final GroupElement and2 = GroupElementFactory.newAndInstance();
+        final GroupElement not1 = GroupElementFactory.newNotInstance();
+        not1.addChild( f );
+        final GroupElement or3 = GroupElementFactory.newOrInstance();
+        or3.addChild( g );
+
+        final GroupElement not2 = GroupElementFactory.newNotInstance();
+        not2.addChild( h );
+        or3.addChild( not2 );
+
+        and2.addChild( not1 );
+        and2.addChild( or3 );
+        and.addChild( and2 );
+
+        final GroupElement[] ands = LogicTransformer.getInstance().transform( and );
+
+        // Uncomment this when you need to output a new known correct tree
+        // result
+//        writeTree( ands,
+//                   "correct_transform1.dat" );
+
+        // Now check the main tree
+
+        // Get known correct tree
+        // The binary stream was created from a handchecked correct output
+        final ObjectInputStream ois = new ObjectInputStream( this.getClass().getResourceAsStream( "/correct_transform1.dat" ) );
+        final GroupElement[] correctResultAnds = (GroupElement[]) ois.readObject();
+
+        for ( int j = 0; j < ands.length; j++ ) {
+            assertEquals( correctResultAnds[j],
+                          ands[j] );
+        }
+    }
+
+    private void writeTree(final Object object,
+                           final String fileName) throws IOException {
+        final String className = this.getClass().getName();
+
+        File file = new File( this.getClass().getResource( className.substring( className.lastIndexOf( '.' ) + 1 ) + ".class" ).getFile() );
+
+        file = new File( file.getParent(),
+                         fileName );
+
+        new ObjectOutputStream( new FileOutputStream( file ) ).writeObject( object );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/PackageCompilationDataTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/PackageCompilationDataTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/PackageCompilationDataTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,45 @@
+package org.drools.rule;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.CodeSource;
+
+import junit.framework.TestCase;
+
+import org.drools.WorkingMemory;
+import org.drools.spi.EvalExpression;
+import org.drools.spi.Tuple;
+
+public class PackageCompilationDataTest extends TestCase {
+    public static class TestEvalExpression implements EvalExpression {
+        public boolean evaluate(Tuple t, Declaration[] d, WorkingMemory w) {
+            return false;
+        }
+    }
+
+    public void testCodeSourceUrl() throws IOException {
+        final String className = TestEvalExpression.class.getName();
+        final PackageCompilationData pcData = new PackageCompilationData(getClass().getClassLoader());
+        final EvalCondition invoker = new EvalCondition(null);
+        pcData.putInvoker(className, invoker);
+        final InputStream is = getClass().getClassLoader().getResourceAsStream(className.replace('.', '/') + ".class");
+        try {
+            pcData.write(className.replace('.', '/') + ".class", read(is));
+        } finally {
+            is.close();
+        }
+        final CodeSource codeSource = invoker.getEvalExpression().getClass().getProtectionDomain().getCodeSource();
+        assertNotNull(codeSource.getLocation());
+    }
+
+    private static byte[] read(final InputStream is) throws IOException {
+        final ByteArrayOutputStream os = new ByteArrayOutputStream();
+        final byte[] b = new byte[1024];
+        int len;
+        while ((len = is.read(b)) > 0) {
+            os.write(b, 0, len);
+        }
+        return os.toByteArray();
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/PatternTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/PatternTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/PatternTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,70 @@
+package org.drools.rule;
+
+import junit.framework.TestCase;
+
+import org.drools.Cheese;
+import org.drools.base.ClassObjectType;
+import org.drools.facttemplates.Fact;
+import org.drools.facttemplates.FactTemplate;
+import org.drools.facttemplates.FactTemplateImpl;
+import org.drools.facttemplates.FactTemplateObjectType;
+import org.drools.facttemplates.FieldTemplate;
+import org.drools.facttemplates.FieldTemplateImpl;
+import org.drools.spi.Extractor;
+import org.drools.spi.ObjectType;
+
+public class PatternTest extends TestCase {
+
+    public void testDeclarationsObjectType() throws Exception {
+        final ObjectType type = new ClassObjectType( Cheese.class );
+        final Pattern col = new Pattern( 0,
+                                       type,
+                                       "foo" );
+        final Declaration dec = col.getDeclaration();
+        final Extractor ext = dec.getExtractor();
+        assertEquals( Cheese.class,
+                      ext.getExtractToClass() );
+
+        final Cheese stilton = new Cheese( "stilton",
+                                           42 );
+
+        assertEquals( stilton,
+                      dec.getValue( null, stilton ) );
+
+    }
+
+    public void testDeclarationsFactTemplate() throws Exception {
+
+        final Package pkg = new Package( "org.store" );
+        final FieldTemplate cheeseName = new FieldTemplateImpl( "name",
+                                                                0,
+                                                                String.class );
+        final FieldTemplate cheesePrice = new FieldTemplateImpl( "price",
+                                                                 1,
+                                                                 Integer.class );
+        final FieldTemplate[] fields = new FieldTemplate[]{cheeseName, cheesePrice};
+        final FactTemplate cheese = new FactTemplateImpl( pkg,
+                                                          "Cheese",
+                                                          fields );
+
+        final ObjectType type = new FactTemplateObjectType( cheese );
+
+        final Pattern col = new Pattern( 0,
+                                       type,
+                                       "foo" );
+        final Declaration dec = col.getDeclaration();
+        final Extractor ext = dec.getExtractor();
+        assertEquals( Fact.class,
+                      ext.getExtractToClass() );
+
+        final Fact stilton = cheese.createFact( 10 );
+        stilton.setFieldValue( "name",
+                               "stilton" );
+        stilton.setFieldValue( "price",
+                               new Integer( 200 ) );
+
+        assertEquals( stilton,
+                      dec.getValue( null, stilton ) );
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/RuleTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/RuleTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/rule/RuleTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,117 @@
+package org.drools.rule;
+
+import java.util.Calendar;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Michael Neale
+ */
+public class RuleTest extends TestCase {
+
+    public void testDateEffective() {
+        final Rule rule = new Rule( "myrule" );
+
+        assertTrue( rule.isEffective(new TimeMachine()) );
+
+        final Calendar earlier = Calendar.getInstance();
+        earlier.setTimeInMillis( 10 );
+
+        rule.setDateEffective( earlier );
+
+        assertTrue( rule.isEffective(new TimeMachine()) );
+
+        final Calendar later = Calendar.getInstance();
+        later.setTimeInMillis( later.getTimeInMillis() + 100000000 );
+
+        assertTrue( later.after( Calendar.getInstance() ) );
+
+        rule.setDateEffective( later );
+        assertFalse( rule.isEffective(new TimeMachine()) );
+
+    }
+
+    public void testDateExpires() throws Exception {
+        final Rule rule = new Rule( "myrule" );
+
+        assertTrue( rule.isEffective(new TimeMachine()) );
+
+        final Calendar earlier = Calendar.getInstance();
+        earlier.setTimeInMillis( 10 );
+
+        rule.setDateExpires( earlier );
+
+        assertFalse( rule.isEffective(new TimeMachine()) );
+
+        final Calendar later = Calendar.getInstance();
+        later.setTimeInMillis( later.getTimeInMillis() + 100000000 );
+
+        rule.setDateExpires( later );
+        assertTrue( rule.isEffective(new TimeMachine()) );
+
+    }
+
+    public void testDateEffectiveExpires() {
+        final Rule rule = new Rule( "myrule" );
+
+        final Calendar past = Calendar.getInstance();
+        past.setTimeInMillis( 10 );
+
+        final Calendar future = Calendar.getInstance();
+        future.setTimeInMillis( future.getTimeInMillis() + 100000000 );
+
+        rule.setDateEffective( past );
+        rule.setDateExpires( future );
+
+        assertTrue( rule.isEffective(new TimeMachine()) );
+
+        rule.setDateExpires( past );
+        assertFalse( rule.isEffective(new TimeMachine()) );
+
+        rule.setDateExpires( future );
+        rule.setDateEffective( future );
+
+
+
+        assertFalse( rule.isEffective(new TimeMachine()) );
+
+    }
+
+    public void testRuleEnabled() {
+        final Rule rule = new Rule( "myrule" );
+        rule.setEnabled( false );
+        assertFalse( rule.isEffective(new TimeMachine()) );
+
+        final Calendar past = Calendar.getInstance();
+        past.setTimeInMillis( 10 );
+
+        rule.setDateEffective( past );
+        assertFalse( rule.isEffective(new TimeMachine()) );
+        rule.setEnabled( true );
+
+        assertTrue( rule.isEffective(new TimeMachine()) );
+    }
+
+    public void testTimeMachine() {
+        final Rule rule = new Rule( "myrule" );
+        rule.setEnabled( true );
+        assertTrue(rule.isEffective(new TimeMachine()));
+
+        final Calendar future = Calendar.getInstance();
+        future.setTimeInMillis( future.getTimeInMillis() + 100000000 );
+        rule.setDateEffective(future);
+        assertFalse(rule.isEffective(new TimeMachine()));
+
+        assertTrue(rule.isEffective(new TimeMachine() {
+        	public Calendar getNow() {
+        		Calendar loveYouLongTime = Calendar.getInstance();
+        		loveYouLongTime.setTimeInMillis(future.getTimeInMillis() + 1000000000000L);
+        		return loveYouLongTime;
+        	}
+        }));
+
+
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/spi/MockConstraint.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/spi/MockConstraint.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/spi/MockConstraint.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,98 @@
+package org.drools.spi;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.WorkingMemory;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.rule.ContextEntry;
+import org.drools.rule.Declaration;
+
+public class MockConstraint
+    implements
+    BetaNodeFieldConstraint {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+
+    public Declaration[]      declarations;
+
+    public boolean            isAllowed        = true;
+
+    public boolean isAllowed(final InternalFactHandle handle,
+                             final Tuple tuple,
+                             final WorkingMemory workingMemory) {
+        return this.isAllowed;
+    }
+
+    public Declaration[] getRequiredDeclarations() {
+        return this.declarations;
+    }
+    
+    public void replaceDeclaration(Declaration oldDecl,
+                                   Declaration newDecl) {
+    }
+
+    public Object clone() {
+        return this;
+    }
+    
+    public ContextEntry getContextEntry() {
+        return new ContextEntry() {
+            private static final long serialVersionUID = 400L;
+            private ContextEntry      next;
+
+            public ContextEntry getNext() {
+                return this.next;
+            }
+
+            public void setNext(final ContextEntry entry) {
+                this.next = entry;
+            }
+
+            public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
+                                             final InternalFactHandle handle) {
+            }
+
+            public void updateFromTuple(final InternalWorkingMemory workingMemory,
+                                        final ReteTuple tuple) {
+            }
+
+            public void resetFactHandle() {
+            }
+
+            public void resetTuple() {
+                // TODO Auto-generated method stub
+                
+            }
+        };
+    }
+
+    public boolean isAllowedCachedLeft(final ContextEntry context,
+                                       final InternalFactHandle handle) {
+        return this.isAllowed;
+    }
+
+    public boolean isAllowedCachedRight(final ReteTuple tuple,
+                                        final ContextEntry context) {
+        return this.isAllowed;
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/spi/MockObjectType.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/spi/MockObjectType.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/spi/MockObjectType.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,101 @@
+package org.drools.spi;
+
+import org.drools.base.ClassObjectType;
+import org.drools.base.ValueType;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Java class semantics <code>ObjectType</code>.
+ * 
+ * @author <a href="mailto:bob at werken.com">bob at werken.com </a>
+ * 
+ * @version $Id: MockObjectType.java,v 1.1 2005/07/26 01:06:34 mproctor Exp $
+ */
+public class MockObjectType
+    implements
+    ObjectType {
+    // ------------------------------------------------------------
+    // Instance members
+    // ------------------------------------------------------------
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 400L;
+    /** Java object class. */
+    private boolean           matches;
+    
+    private boolean           isEvent;
+
+    // ------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------
+
+    /**
+     * Construct.
+     * 
+     * @param objectTypeClass
+     *            Java object class.
+     */
+    public MockObjectType(final boolean matches) {
+        this.matches = matches;
+    }
+
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // org.drools.spi.ObjectType
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+    /**
+     * Determine if the passed <code>Object</code> belongs to the object type
+     * defined by this <code>objectType</code> instance.
+     * 
+     * @param object
+     *            The <code>Object</code> to test.
+     * 
+     * @return <code>true</code> if the <code>Object</code> matches this
+     *         object type, else <code>false</code>.
+     */
+    public boolean matches(final Object object) {
+        return this.matches;
+    }
+    
+    public boolean isAssignableFrom(Object object) {
+        return this.matches;
+    }
+    
+    public boolean isAssignableFrom(ObjectType objectType) {
+        return this.matches;
+    } 
+
+    public ValueType getValueType() {
+        return ValueType.OBJECT_TYPE;
+    }
+
+    public boolean isEvent() {
+        return isEvent;
+    }
+
+    public void setEvent(boolean isEvent) {
+        this.isEvent = isEvent;
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/BaseQueueable.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/BaseQueueable.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/BaseQueueable.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,128 @@
+package org.drools.util;
+
+import org.drools.common.ActivationGroupNode;
+import org.drools.common.LogicalDependency;
+import org.drools.common.RuleFlowGroupNode;
+import org.drools.rule.GroupElement;
+import org.drools.rule.Rule;
+import org.drools.spi.AgendaGroup;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class BaseQueueable
+    implements
+    Queueable {
+    private Queue queue;
+    private int   index;
+
+    public void enqueued(final Queue queue,
+                         final int index) {
+        this.queue = queue;
+        this.index = index;
+    }
+
+    public void dequeue() {
+        this.queue.dequeue( this.index );
+    }
+
+    public void addLogicalDependency(LogicalDependency node) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public ActivationGroupNode getActivationGroupNode() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public long getActivationNumber() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public AgendaGroup getAgendaGroup() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public LinkedList getLogicalDependencies() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public PropagationContext getPropagationContext() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Rule getRule() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public RuleFlowGroupNode getRuleFlowGroupNode() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public int getSalience() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public GroupElement getSubRule() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Tuple getTuple() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public boolean isActivated() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public void remove() {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public void setActivated(boolean activated) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public void setActivationGroupNode(ActivationGroupNode activationGroupNode) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public void setLogicalDependencies(LinkedList justified) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public void setRuleFlowGroupNode(RuleFlowGroupNode ruleFlowGroupNode) {
+        // TODO Auto-generated method stub
+        
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/BinaryHeapPriorityQueueTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/BinaryHeapPriorityQueueTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/BinaryHeapPriorityQueueTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,96 @@
+package org.drools.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+
+import junit.framework.TestCase;
+
+public class BinaryHeapPriorityQueueTest extends TestCase {
+    public void testOptimised() {
+        final Random random = new Random();
+        final List items = new LinkedList();
+
+        final Queue queue = new BinaryHeapQueue( NaturalComparator.INSTANCE,
+                                                 100000 );
+
+        for ( int i = 0; i < 100000; ++i ) {
+            items.add( new LongQueueable( random.nextLong() ) );
+        }
+
+        final long startEnqueue = System.currentTimeMillis();
+
+        for ( final Iterator i = items.iterator(); i.hasNext(); ) {
+            queue.enqueue( (Queueable) i.next() );
+        }
+
+        final long elapsedEnqueue = System.currentTimeMillis() - startEnqueue;
+
+        final long startDequeue = System.currentTimeMillis();
+
+        for ( final Iterator i = items.iterator(); i.hasNext(); ) {
+            ((Queueable) i.next()).dequeue();
+        }
+
+        //        while (!queue.isEmpty()) {
+        //            queue.dequeue();
+        //        }
+
+        final long elapsedDequeue = System.currentTimeMillis() - startDequeue;
+
+        //        System.out.println( "elapsedEnqueue = " + elapsedEnqueue );
+        //        System.out.println( "elapsedDequeue = " + elapsedDequeue );
+    }
+
+    public void testBasic() {
+        final Random random = new Random();
+        final List items = new LinkedList();
+
+        final BinaryHeapQueue queue = new BinaryHeapQueue( NaturalComparator.INSTANCE,
+                                                           100000 );
+
+        for ( int i = 0; i < 100000; ++i ) {
+            items.add( new LongQueueable( random.nextLong() ) );
+        }
+
+        final long startEnqueue = System.currentTimeMillis();
+
+        for ( final Iterator i = items.iterator(); i.hasNext(); ) {
+            queue.enqueue( (Queueable) i.next() );
+        }
+
+        final long elapsedEnqueue = System.currentTimeMillis() - startEnqueue;
+
+        final long startDequeue = System.currentTimeMillis();
+
+        for ( final Iterator i = items.iterator(); i.hasNext(); ) {
+            queue.enqueue( (Queueable) i.next() );
+        }
+
+        //        while (!queue.isEmpty()) {
+        //            queue.pop();
+        //        }
+
+        final long elapsedDequeue = System.currentTimeMillis() - startDequeue;
+
+        //        System.out.println( "elapsedEnqueue = " + elapsedEnqueue );
+        //        System.out.println( "elapsedDequeue = " + elapsedDequeue );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/ClassUtilsTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/ClassUtilsTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/ClassUtilsTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,61 @@
+package org.drools.util;
+
+import junit.framework.TestCase;
+
+public class ClassUtilsTest extends TestCase {
+
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    public void testCanonicalNameSimpleClass() {
+        String name = ClassUtils.canonicalName( ClassUtilsTest.class );
+        assertEquals( "org.drools.util.ClassUtilsTest",
+                      name );
+    }
+
+    public void testCanonicalNameInnerClass() {
+        String name = ClassUtils.canonicalName( A.class );
+        assertEquals( "org.drools.util.ClassUtilsTest.A",
+                      name );
+    }
+    
+    public void testCanonicalNameInnerInnerClass() {
+        String name = ClassUtils.canonicalName( A.B.class );
+        assertEquals( "org.drools.util.ClassUtilsTest.A.B",
+                      name );
+    }
+    
+    public void testCanonicalNameArray() {
+        String name = ClassUtils.canonicalName( Object[].class );
+        assertEquals( "java.lang.Object[]",
+                      name );
+    }
+    
+    public void testCanonicalNameMultiIndexArray() {
+        String name = ClassUtils.canonicalName( Object[][][].class );
+        assertEquals( "java.lang.Object[][][]",
+                      name );
+    }
+    
+    public void testCanonicalNameMultiIndexArrayInnerClass() {
+        String name = ClassUtils.canonicalName( A.B[][][].class );
+        assertEquals( "org.drools.util.ClassUtilsTest.A.B[][][]",
+                      name );
+    }
+    
+    public void testCanonicalNameMultiIndexArrayPrimitives() {
+        String name = ClassUtils.canonicalName( long[][][].class );
+        assertEquals( "long[][][]",
+                      name );
+    }
+    
+    public static class A {
+        public static class B {
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/FactHashTableTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/FactHashTableTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/FactHashTableTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,15 @@
+package org.drools.util;
+
+import junit.framework.TestCase;
+
+import org.drools.util.ObjectHashMap.ObjectEntry;
+
+public class FactHashTableTest extends TestCase {
+    public void testEmptyIterator() {
+        final FactHashTable map = new FactHashTable();
+        final Iterator it = map.iterator();
+        for ( ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next() ) {
+            fail( "Map is empty, there should be no iteration" );
+        }
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/FieldIndexEntryTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/FieldIndexEntryTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/FieldIndexEntryTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,189 @@
+package org.drools.util;
+
+import junit.framework.TestCase;
+
+import org.drools.Cheese;
+import org.drools.base.ClassFieldExtractor;
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.EqualityEvaluatorsDefinition;
+import org.drools.base.evaluators.Operator;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.util.AbstractHashTable.FactEntryImpl;
+import org.drools.util.AbstractHashTable.FieldIndex;
+import org.drools.util.AbstractHashTable.SingleIndex;
+import org.drools.util.FactHandleIndexHashTable.FieldIndexEntry;
+
+public class FieldIndexEntryTest extends TestCase {
+    ClassFieldExtractorCache cache = ClassFieldExtractorCache.getInstance();
+    EqualityEvaluatorsDefinition equals = new EqualityEvaluatorsDefinition();
+
+    public void testSingleEntry() {
+        final ClassFieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                                  "type",
+                                                                  getClass().getClassLoader() );
+
+        final FieldIndex fieldIndex = new FieldIndex( extractor,
+                                                      null,
+                                                      equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ) );
+        final SingleIndex singleIndex = new SingleIndex( new FieldIndex[]{fieldIndex},
+                                                         1 );
+
+        final FieldIndexEntry index = new FieldIndexEntry( singleIndex,
+                                                           "stilton".hashCode() );
+
+        // Test initial construction
+        assertNull( index.getFirst() );
+        assertEquals( "stilton".hashCode(),
+                      index.hashCode() );
+
+        final Cheese stilton1 = new Cheese( "stilton",
+                                            35 );
+        final InternalFactHandle h1 = new DefaultFactHandle( 1,
+                                                             stilton1 );
+
+        // test add
+        index.add( h1 );
+
+        final FactEntryImpl entry1 = index.getFirst();
+        assertSame( h1,
+                    entry1.getFactHandle() );
+        assertNull( entry1.getNext() );
+        assertSame( entry1,
+                    index.get( h1 ) );
+
+        // test get
+        final FactEntryImpl entry2 = index.get( h1 );
+        assertSame( entry1,
+                    entry2 );
+
+        // test remove
+        index.remove( h1 );
+        assertNull( index.getFirst() );
+    }
+
+    public void testTwoEntries() {
+        final ClassFieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                                  "type",
+                                                                  getClass().getClassLoader() );
+        final FieldIndex fieldIndex = new FieldIndex( extractor,
+                                                      null,
+                                                      equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ) );
+        final SingleIndex singleIndex = new SingleIndex( new FieldIndex[]{fieldIndex},
+                                                         1 );
+
+        final FieldIndexEntry index = new FieldIndexEntry( singleIndex,
+                                                           "stilton".hashCode() );
+
+        final Cheese stilton1 = new Cheese( "stilton",
+                                            35 );
+        final InternalFactHandle h1 = new DefaultFactHandle( 1,
+                                                             stilton1 );
+        final Cheese stilton2 = new Cheese( "stilton",
+                                            59 );
+        final InternalFactHandle h2 = new DefaultFactHandle( 2,
+                                                             stilton2 );
+
+        // test add
+        index.add( h1 );
+        index.add( h2 );
+        assertEquals( h2,
+                      index.getFirst().getFactHandle() );
+        assertEquals( h1,
+                      ((FactEntryImpl) index.getFirst().getNext()).getFactHandle() );
+
+        // test get
+        assertEquals( h1,
+                      index.get( h1 ).getFactHandle() );
+        assertEquals( h2,
+                      index.get( h2 ).getFactHandle() );
+
+        // test removal for combinations
+        // remove first
+        index.remove( h2 );
+        assertEquals( h1,
+                      index.getFirst().getFactHandle() );
+
+        // remove second
+        index.add( h2 );
+        index.remove( h1 );
+        assertEquals( h2,
+                      index.getFirst().getFactHandle() );
+
+        // check index type does not change, as this fact is removed
+        stilton1.setType( "cheddar" );
+    }
+
+    public void testThreeEntries() {
+        final ClassFieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                                  "type",
+                                                                  getClass().getClassLoader() );
+        final FieldIndex fieldIndex = new FieldIndex( extractor,
+                                                      null,
+                                                      equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ) );
+        final SingleIndex singleIndex = new SingleIndex( new FieldIndex[]{fieldIndex},
+                                                         1 );
+
+        final FieldIndexEntry index = new FieldIndexEntry( singleIndex,
+                                                           "stilton".hashCode() );
+
+        final Cheese stilton1 = new Cheese( "stilton",
+                                            35 );
+        final InternalFactHandle h1 = new DefaultFactHandle( 1,
+                                                             stilton1 );
+        final Cheese stilton2 = new Cheese( "stilton",
+                                            59 );
+        final InternalFactHandle h2 = new DefaultFactHandle( 2,
+                                                             stilton2 );
+        final Cheese stilton3 = new Cheese( "stilton",
+                                            59 );
+        final InternalFactHandle h3 = new DefaultFactHandle( 3,
+                                                             stilton3 );
+
+        // test add
+        index.add( h1 );
+        index.add( h2 );
+        index.add( h3 );
+        assertEquals( h3,
+                      index.getFirst().getFactHandle() );
+        assertEquals( h2,
+                      ((FactEntryImpl) index.getFirst().getNext()).getFactHandle() );
+        assertEquals( h1,
+                      ((FactEntryImpl) index.getFirst().getNext().getNext()).getFactHandle() );
+
+        // test get
+        assertEquals( h1,
+                      index.get( h1 ).getFactHandle() );
+        assertEquals( h2,
+                      index.get( h2 ).getFactHandle() );
+        assertEquals( h3,
+                      index.get( h3 ).getFactHandle() );
+
+        // test removal for combinations
+        //remove first
+        index.remove( h3 );
+        assertEquals( h2,
+                      index.getFirst().getFactHandle() );
+        assertEquals( h1,
+                      ((FactEntryImpl) index.getFirst().getNext()).getFactHandle() );
+
+        index.add( h3 );
+        index.remove( h2 );
+        assertEquals( h3,
+                      index.getFirst().getFactHandle() );
+        assertEquals( h1,
+                      ((FactEntryImpl) index.getFirst().getNext()).getFactHandle() );
+
+        index.add( h2 );
+        index.remove( h1 );
+        assertEquals( h2,
+                      index.getFirst().getFactHandle() );
+        assertEquals( h3,
+                      ((FactEntryImpl) index.getFirst().getNext()).getFactHandle() );
+
+        index.remove( index.getFirst().getFactHandle() );
+        // check index type does not change, as this fact is removed
+        stilton2.setType( "cheddar" );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/FieldIndexHashTableTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/FieldIndexHashTableTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/FieldIndexHashTableTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,553 @@
+package org.drools.util;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.drools.Cheese;
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.ClassObjectType;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.EqualityEvaluatorsDefinition;
+import org.drools.base.evaluators.Operator;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.reteoo.ReteTuple;
+import org.drools.rule.Declaration;
+import org.drools.rule.Pattern;
+import org.drools.spi.FieldExtractor;
+import org.drools.util.AbstractHashTable.FactEntryImpl;
+import org.drools.util.AbstractHashTable.FieldIndex;
+import org.drools.util.FactHandleIndexHashTable.FieldIndexEntry;
+import org.drools.util.ObjectHashMap.ObjectEntry;
+
+public class FieldIndexHashTableTest extends TestCase {
+    ClassFieldExtractorCache cache = ClassFieldExtractorCache.getInstance();
+    EqualityEvaluatorsDefinition equals = new EqualityEvaluatorsDefinition();
+
+    public void testSingleEntry() throws Exception {
+        final FieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                             "type",
+                                                             getClass().getClassLoader() );
+
+        final Pattern pattern = new Pattern( 0,
+                                             new ClassObjectType( Cheese.class ) );
+
+        final Declaration declaration = new Declaration( "typeOfCheese",
+                                                         extractor,
+                                                         pattern );
+
+        final FieldIndex fieldIndex = new FieldIndex( extractor,
+                                                      declaration,
+                                                      equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ) );
+
+        final FactHandleIndexHashTable map = new FactHandleIndexHashTable( new FieldIndex[]{fieldIndex} );
+
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           10 );
+        final InternalFactHandle cheddarHandle1 = new DefaultFactHandle( 0,
+                                                                         cheddar );
+
+        assertEquals( 0,
+                      map.size() );
+        assertNull( map.get( new ReteTuple( cheddarHandle1 ) ) );
+
+        final Cheese stilton1 = new Cheese( "stilton",
+                                            35 );
+        final InternalFactHandle stiltonHandle1 = new DefaultFactHandle( 1,
+                                                                         stilton1 );
+        map.add( stiltonHandle1 );
+
+        assertEquals( 1,
+                      map.size() );
+        assertEquals( 1,
+                      tablePopulationSize( map ) );
+
+        final Cheese stilton2 = new Cheese( "stilton",
+                                            80 );
+        final InternalFactHandle stiltonHandle2 = new DefaultFactHandle( 2,
+                                                                         stilton2 );
+
+        final FieldIndexEntry stiltonEntry = map.get( new ReteTuple( stiltonHandle2 ) );
+        assertSame( stiltonHandle1,
+                    stiltonEntry.getFirst().getFactHandle() );
+        assertNull( stiltonEntry.getFirst().getNext() );
+    }
+
+    public void testTwoDifferentEntries() throws Exception {
+        final FieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                             "type",
+                                                             getClass().getClassLoader() );
+
+        final Pattern pattern = new Pattern( 0,
+                                             new ClassObjectType( Cheese.class ) );
+
+        final Declaration declaration = new Declaration( "typeOfCheese",
+                                                         extractor,
+                                                         pattern );
+
+        final FieldIndex fieldIndex = new FieldIndex( extractor,
+                                                      declaration,
+                                                      equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ) );
+
+        final FactHandleIndexHashTable map = new FactHandleIndexHashTable( new FieldIndex[]{fieldIndex} );
+
+        assertEquals( 0,
+                      map.size() );
+
+        final Cheese stilton1 = new Cheese( "stilton",
+                                            35 );
+        final InternalFactHandle stiltonHandle1 = new DefaultFactHandle( 1,
+                                                                         stilton1 );
+        map.add( stiltonHandle1 );
+
+        final Cheese cheddar1 = new Cheese( "cheddar",
+                                            35 );
+        final InternalFactHandle cheddarHandle1 = new DefaultFactHandle( 2,
+                                                                         cheddar1 );
+        map.add( cheddarHandle1 );
+
+        assertEquals( 2,
+                      map.size() );
+        assertEquals( 2,
+                      tablePopulationSize( map ) );
+
+        final Cheese stilton2 = new Cheese( "stilton",
+                                            77 );
+        final InternalFactHandle stiltonHandle2 = new DefaultFactHandle( 2,
+                                                                         stilton2 );
+        final FieldIndexEntry stiltonEntry = map.get( new ReteTuple( stiltonHandle2 ) );
+        assertSame( stiltonHandle1,
+                    stiltonEntry.getFirst().getFactHandle() );
+        assertNull( stiltonEntry.getFirst().getNext() );
+
+        final Cheese cheddar2 = new Cheese( "cheddar",
+                                            5 );
+        final InternalFactHandle cheddarHandle2 = new DefaultFactHandle( 2,
+                                                                         cheddar2 );
+        final FieldIndexEntry cheddarEntry = map.get( new ReteTuple( cheddarHandle2 ) );
+        assertSame( cheddarHandle1,
+                    cheddarEntry.getFirst().getFactHandle() );
+        assertNull( cheddarEntry.getFirst().getNext() );
+    }
+
+    public void testTwoEqualEntries() throws Exception {
+        final FieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                             "type",
+                                                             getClass().getClassLoader() );
+
+        final Pattern pattern = new Pattern( 0,
+                                             new ClassObjectType( Cheese.class ) );
+
+        final Declaration declaration = new Declaration( "typeOfCheese",
+                                                         extractor,
+                                                         pattern );
+
+        final FieldIndex fieldIndex = new FieldIndex( extractor,
+                                                      declaration,
+                                                      equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ) );
+
+        final FactHandleIndexHashTable map = new FactHandleIndexHashTable( new FieldIndex[]{fieldIndex} );
+
+        assertEquals( 0,
+                      map.size() );
+
+        final Cheese stilton1 = new Cheese( "stilton",
+                                            35 );
+        final InternalFactHandle stiltonHandle1 = new DefaultFactHandle( 1,
+                                                                         stilton1 );
+        map.add( stiltonHandle1 );
+
+        final Cheese cheddar1 = new Cheese( "cheddar",
+                                            35 );
+        final InternalFactHandle cheddarHandle1 = new DefaultFactHandle( 2,
+                                                                         cheddar1 );
+        map.add( cheddarHandle1 );
+
+        final Cheese stilton2 = new Cheese( "stilton",
+                                            81 );
+        final InternalFactHandle stiltonHandle2 = new DefaultFactHandle( 3,
+                                                                         stilton2 );
+        map.add( stiltonHandle2 );
+
+        assertEquals( 3,
+                      map.size() );
+        assertEquals( 2,
+                      tablePopulationSize( map ) );
+
+        // Check they are correctly chained to the same FieldIndexEntry
+        final Cheese stilton3 = new Cheese( "stilton",
+                                            89 );
+        final InternalFactHandle stiltonHandle3 = new DefaultFactHandle( 4,
+                                                                         stilton2 );
+
+        final FieldIndexEntry stiltonEntry = map.get( new ReteTuple( stiltonHandle3 ) );
+        assertSame( stiltonHandle2,
+                    stiltonEntry.getFirst().getFactHandle() );
+        assertSame( stiltonHandle1,
+                    ((FactEntryImpl) stiltonEntry.getFirst().getNext()).getFactHandle() );
+    }
+
+    public void testTwoDifferentEntriesSameHashCode() throws Exception {
+        final FieldExtractor extractor = cache.getExtractor( TestClass.class,
+                                                             "object",
+                                                             getClass().getClassLoader() );
+
+        final Pattern pattern = new Pattern( 0,
+                                             new ClassObjectType( TestClass.class ) );
+
+        final Declaration declaration = new Declaration( "theObject",
+                                                         extractor,
+                                                         pattern );
+
+        final FieldIndex fieldIndex = new FieldIndex( extractor,
+                                                      declaration,
+                                                      equals.getEvaluator( ValueType.OBJECT_TYPE, Operator.EQUAL ) );
+
+        final FactHandleIndexHashTable map = new FactHandleIndexHashTable( new FieldIndex[]{fieldIndex} );
+
+        final TestClass c1 = new TestClass( 0,
+                                            new TestClass( 20,
+                                                           "stilton" ) );
+
+        final InternalFactHandle ch1 = new DefaultFactHandle( 1,
+                                                              c1 );
+
+        map.add( ch1 );
+
+        final TestClass c2 = new TestClass( 0,
+                                            new TestClass( 20,
+                                                           "cheddar" ) );
+        final InternalFactHandle ch2 = new DefaultFactHandle( 2,
+                                                              c2 );
+        map.add( ch2 );
+
+        // same hashcode, but different values, so it should result in  a size of 2
+        assertEquals( 2,
+                      map.size() );
+
+        // however both are in the same table bucket
+        assertEquals( 1,
+                      tablePopulationSize( map ) );
+
+        // this table bucket will have two FieldIndexEntries, as they are actually two different values
+        final FieldIndexEntry entry = (FieldIndexEntry) getEntries( map )[0];
+
+    }
+
+    public void testRemove() throws Exception {
+        final FieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                             "type",
+                                                             getClass().getClassLoader() );
+
+        final Pattern pattern = new Pattern( 0,
+                                             new ClassObjectType( Cheese.class ) );
+
+        final Declaration declaration = new Declaration( "typeOfCheese",
+                                                         extractor,
+                                                         pattern );
+
+        final FieldIndex fieldIndex = new FieldIndex( extractor,
+                                                      declaration,
+                                                      equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ) );
+
+        final FactHandleIndexHashTable map = new FactHandleIndexHashTable( new FieldIndex[]{fieldIndex} );
+
+        assertEquals( 0,
+                      map.size() );
+
+        final Cheese stilton1 = new Cheese( "stilton",
+                                            35 );
+        final InternalFactHandle stiltonHandle1 = new DefaultFactHandle( 1,
+                                                                         stilton1 );
+        map.add( stiltonHandle1 );
+
+        final Cheese cheddar1 = new Cheese( "cheddar",
+                                            35 );
+        final InternalFactHandle cheddarHandle1 = new DefaultFactHandle( 2,
+                                                                         cheddar1 );
+        map.add( cheddarHandle1 );
+
+        final Cheese stilton2 = new Cheese( "stilton",
+                                            81 );
+        final InternalFactHandle stiltonHandle2 = new DefaultFactHandle( 3,
+                                                                         stilton2 );
+        map.add( stiltonHandle2 );
+
+        assertEquals( 3,
+                      map.size() );
+        assertEquals( 2,
+                      tablePopulationSize( map ) );
+
+        // cheddar is in its own buccket, which should be removed once empty. We cannot have
+        // empty FieldIndexEntries in the Map, as they get their value  from the first FactEntry.
+        map.remove( cheddarHandle1 );
+        assertEquals( 2,
+                      map.size() );
+        assertEquals( 1,
+                      tablePopulationSize( map ) );
+
+        // We remove t he stiltonHandle2, but there is still  one more stilton, so size  should be the same
+        map.remove( stiltonHandle2 );
+        assertEquals( 1,
+                      map.size() );
+        assertEquals( 1,
+                      tablePopulationSize( map ) );
+
+        //  No more stiltons, so the table should be empty
+        map.remove( stiltonHandle1 );
+        assertEquals( 0,
+                      map.size() );
+        assertEquals( 0,
+                      tablePopulationSize( map ) );
+    }
+
+    public void testResize() throws Exception {
+        final FieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                             "type",
+                                                             getClass().getClassLoader() );
+
+        final Pattern pattern = new Pattern( 0,
+                                             new ClassObjectType( Cheese.class ) );
+
+        final Declaration declaration = new Declaration( "typeOfCheese",
+                                                         extractor,
+                                                         pattern );
+
+        final FieldIndex fieldIndex = new FieldIndex( extractor,
+                                                      declaration,
+                                                      equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ) );
+
+        final FactHandleIndexHashTable map = new FactHandleIndexHashTable( new FieldIndex[]{fieldIndex} );
+
+        assertEquals( 0,
+                      map.size() );
+
+        final Cheese stilton1 = new Cheese( "stilton",
+                                            35 );
+        map.add( new DefaultFactHandle( 1,
+                                        stilton1 ) );
+
+        final Cheese stilton2 = new Cheese( "stilton",
+                                            81 );
+        map.add( new DefaultFactHandle( 2,
+                                        stilton2 ) );
+
+        final Cheese cheddar1 = new Cheese( "cheddar",
+                                            35 );
+        map.add( new DefaultFactHandle( 3,
+                                        cheddar1 ) );
+
+        final Cheese cheddar2 = new Cheese( "cheddar",
+                                            38 );
+        map.add( new DefaultFactHandle( 4,
+                                        cheddar2 ) );
+
+        final Cheese brie = new Cheese( "brie",
+                                        293 );
+        map.add( new DefaultFactHandle( 5,
+                                        brie ) );
+
+        final Cheese mozerella = new Cheese( "mozerella",
+                                             15 );
+        map.add( new DefaultFactHandle( 6,
+                                        mozerella ) );
+
+        final Cheese dolcelatte = new Cheese( "dolcelatte",
+                                              284 );
+        map.add( new DefaultFactHandle( 7,
+                                        dolcelatte ) );
+
+        final Cheese camembert1 = new Cheese( "camembert",
+                                              924 );
+        map.add( new DefaultFactHandle( 8,
+                                        camembert1 ) );
+
+        final Cheese camembert2 = new Cheese( "camembert",
+                                              765 );
+        map.add( new DefaultFactHandle( 9,
+                                        camembert2 ) );
+
+        final Cheese redLeicestor = new Cheese( "red leicestor",
+                                                23 );
+        map.add( new DefaultFactHandle( 10,
+                                        redLeicestor ) );
+
+        final Cheese wensleydale = new Cheese( "wensleydale",
+                                               20 );
+        map.add( new DefaultFactHandle( 11,
+                                        wensleydale ) );
+
+        final Cheese edam = new Cheese( "edam",
+                                        12 );
+        map.add( new DefaultFactHandle( 12,
+                                        edam ) );
+
+        final Cheese goude1 = new Cheese( "goude",
+                                          93 );
+        map.add( new DefaultFactHandle( 13,
+                                        goude1 ) );
+
+        final Cheese goude2 = new Cheese( "goude",
+                                          88 );
+        map.add( new DefaultFactHandle( 14,
+                                        goude2 ) );
+
+        final Cheese gruyere = new Cheese( "gruyere",
+                                           82 );
+        map.add( new DefaultFactHandle( 15,
+                                        gruyere ) );
+
+        final Cheese emmental = new Cheese( "emmental",
+                                            98 );
+        map.add( new DefaultFactHandle( 16,
+                                        emmental ) );
+
+        // At this point we have 16 facts but only 12 different types of cheeses
+        // so no table resize and thus its size is 16
+
+        assertEquals( 16,
+                      map.size() );
+
+        Entry[] table = map.getTable();
+        assertEquals( 16,
+                      table.length );
+
+        final Cheese feta = new Cheese( "feta",
+                                        48 );
+        map.add( new DefaultFactHandle( 2,
+                                        feta ) );
+
+        // This adds our 13th type of cheese. The map is set with an initial capacity of 16 and
+        // a threshold of 75%, that after 12 it should resize the map to 32.
+        assertEquals( 17,
+                      map.size() );
+
+        table = map.getTable();
+        assertEquals( 32,
+                      table.length );
+
+        final Cheese haloumi = new Cheese( "haloumi",
+                                           48 );
+        map.add( new DefaultFactHandle( 2,
+                                        haloumi ) );
+
+        final Cheese chevre = new Cheese( "chevre",
+                                          48 );
+        map.add( new DefaultFactHandle( 2,
+                                        chevre ) );
+
+    }
+
+    public static class TestClass {
+        private int    hashCode;
+        private Object object;
+
+        public TestClass() {
+
+        }
+
+        public TestClass(final int hashCode,
+                         final Object object) {
+            this.hashCode = hashCode;
+            this.object = object;
+        }
+
+        public Object getObject() {
+            return this.object;
+        }
+
+        public void setObject(final Object object) {
+            this.object = object;
+        }
+
+        public void setHashCode(final int hashCode) {
+            this.hashCode = hashCode;
+        }
+
+        public int hashCode() {
+            return this.hashCode;
+        }
+
+        public boolean equals(final Object obj) {
+            if ( this == obj ) {
+                return true;
+            }
+            if ( obj == null ) {
+                return false;
+            }
+            if ( getClass() != obj.getClass() ) {
+                return false;
+            }
+            final TestClass other = (TestClass) obj;
+
+            if ( this.object == null ) {
+                if ( other.object != null ) {
+                    return false;
+                }
+            } else if ( !this.object.equals( other.object ) ) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    private int tablePopulationSize(final AbstractHashTable map) throws Exception {
+        final Field field = AbstractHashTable.class.getDeclaredField( "table" );
+        field.setAccessible( true );
+        final Entry[] array = (Entry[]) field.get( map );
+        int size = 0;
+        for ( int i = 0, length = array.length; i < length; i++ ) {
+            if ( array[i] != null ) {
+                size++;
+            }
+        }
+        return size;
+    }
+
+    private Entry[] getEntries(final AbstractHashTable map) throws Exception {
+        final Field field = AbstractHashTable.class.getDeclaredField( "table" );
+        field.setAccessible( true );
+        final List list = new ArrayList();
+
+        final Entry[] array = (Entry[]) field.get( map );
+        for ( int i = 0, length = array.length; i < length; i++ ) {
+            if ( array[i] != null ) {
+                list.add( array[i] );
+            }
+        }
+        return (Entry[]) list.toArray( new Entry[list.size()] );
+    }
+
+    public void testEmptyIterator() {
+        final FieldExtractor extractor = cache.getExtractor( Cheese.class,
+                                                             "type",
+                                                             getClass().getClassLoader() );
+
+        final Pattern pattern = new Pattern( 0,
+                                             new ClassObjectType( Cheese.class ) );
+
+        final Declaration declaration = new Declaration( "typeOfCheese",
+                                                         extractor,
+                                                         pattern );
+
+        final FieldIndex fieldIndex = new FieldIndex( extractor,
+                                                      declaration,
+                                                      equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ) );
+
+        final FactHandleIndexHashTable map = new FactHandleIndexHashTable( new FieldIndex[]{fieldIndex} );
+
+        final Cheese stilton = new Cheese( "stilton",
+                                           55 );
+        final InternalFactHandle stiltonHandle = new DefaultFactHandle( 2,
+                                                                        stilton );
+
+        final Iterator it = map.iterator( new ReteTuple( stiltonHandle ) );
+        for ( ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next() ) {
+            fail( "Map is empty, there should be no iteration" );
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/LinkedListTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/LinkedListTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/LinkedListTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,277 @@
+package org.drools.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+public class LinkedListTest extends TestCase {
+
+    LinkedList     list  = null;
+    LinkedListNode node1 = null;
+    LinkedListNode node2 = null;
+    LinkedListNode node3 = null;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        this.list = new LinkedList();
+        this.node1 = new AbstractBaseLinkedListNode();
+        this.node2 = new AbstractBaseLinkedListNode();
+        this.node3 = new AbstractBaseLinkedListNode();
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /*
+     * Test method for 'org.drools.util.LinkedList.add(LinkedListNode)'
+     */
+    public void testAdd() {
+        this.list.add( this.node1 );
+        Assert.assertNull( "Node1 previous should be null",
+                           this.node1.getPrevious() );
+        Assert.assertNull( "Node1 next should be null",
+                           this.node1.getNext() );
+        Assert.assertSame( "First node should be node1",
+                           this.list.getFirst(),
+                           this.node1 );
+        Assert.assertSame( "Last node should be node1",
+                           this.list.getLast(),
+                           this.node1 );
+
+        this.list.add( this.node2 );
+        Assert.assertSame( "node1 next should be node2",
+                           this.node1.getNext(),
+                           this.node2 );
+        Assert.assertSame( "node2 previous should be node1",
+                           this.node2.getPrevious(),
+                           this.node1 );
+        Assert.assertSame( "First node should be node1",
+                           this.list.getFirst(),
+                           this.node1 );
+        Assert.assertSame( "Last node should be node2",
+                           this.list.getLast(),
+                           this.node2 );
+
+        this.list.add( this.node3 );
+        Assert.assertSame( "node2 next should be node3",
+                           this.node2.getNext(),
+                           this.node3 );
+        Assert.assertSame( "node3 previous should be node2",
+                           this.node3.getPrevious(),
+                           this.node2 );
+        Assert.assertEquals( "LinkedList should have 3 nodes",
+                             this.list.size(),
+                             3 );
+        Assert.assertSame( "First node should be node1",
+                           this.list.getFirst(),
+                           this.node1 );
+        Assert.assertSame( "Last node should be node3",
+                           this.list.getLast(),
+                           this.node3 );
+    }
+
+    /*
+     * Test method for 'org.drools.util.LinkedList.remove(LinkedListNode)'
+     */
+    public void testRemove() {
+        this.list.add( this.node1 );
+        this.list.add( this.node2 );
+        this.list.add( this.node3 );
+
+        Assert.assertSame( "Node2 previous should be node1",
+                           this.node2.getPrevious(),
+                           this.node1 );
+        Assert.assertSame( "Node2 next should be node3",
+                           this.node2.getNext(),
+                           this.node3 );
+        this.list.remove( this.node2 );
+        Assert.assertNull( "Node2 previous should be null",
+                           this.node2.getPrevious() );
+        Assert.assertNull( "Node2 next should be null",
+                           this.node2.getNext() );
+
+        Assert.assertNull( "Node1 previous should be null",
+                           this.node1.getPrevious() );
+        Assert.assertSame( "Node1 next should be node3",
+                           this.node1.getNext(),
+                           this.node3 );
+        this.list.remove( this.node1 );
+        Assert.assertNull( "Node1 previous should be null",
+                           this.node1.getPrevious() );
+        Assert.assertNull( "Node1 next should be null",
+                           this.node1.getNext() );
+
+        Assert.assertNull( "Node3 previous should be null",
+                           this.node3.getPrevious() );
+        Assert.assertNull( "Node3 next should be null",
+                           this.node3.getNext() );
+        this.list.remove( this.node3 );
+        Assert.assertNull( "Node3 previous should be null",
+                           this.node3.getPrevious() );
+        Assert.assertNull( "Node3 next should be null",
+                           this.node3.getNext() );
+    }
+
+    /*
+     * Test method for 'org.drools.util.LinkedList.getFirst()'
+     */
+    public void testGetFirst() {
+        Assert.assertNull( "Empty list should return null on getFirst()",
+                           this.list.getFirst() );
+        this.list.add( this.node1 );
+        Assert.assertSame( "List should return node1 on getFirst()",
+                           this.list.getFirst(),
+                           this.node1 );
+        this.list.add( this.node2 );
+        Assert.assertSame( "List should return node1 on getFirst()",
+                           this.list.getFirst(),
+                           this.node1 );
+        this.list.add( this.node3 );
+        Assert.assertSame( "List should return node1 on getFirst()",
+                           this.list.getFirst(),
+                           this.node1 );
+    }
+
+    /*
+     * Test method for 'org.drools.util.LinkedList.getLast()'
+     */
+    public void testGetLast() {
+        Assert.assertNull( "Empty list should return null on getLast()",
+                           this.list.getLast() );
+        this.list.add( this.node1 );
+        Assert.assertSame( "List should return node1 on getLast()",
+                           this.list.getLast(),
+                           this.node1 );
+        this.list.add( this.node2 );
+        Assert.assertSame( "List should return node2 on getLast()",
+                           this.list.getLast(),
+                           this.node2 );
+        this.list.add( this.node3 );
+        Assert.assertSame( "List should return node3 on getLast()",
+                           this.list.getLast(),
+                           this.node3 );
+    }
+
+    /*
+     * Test method for 'org.drools.util.LinkedList.removeFirst()'
+     */
+    public void testRemoveFirst() {
+        this.list.add( this.node1 );
+        this.list.add( this.node2 );
+        this.list.add( this.node3 );
+
+        Assert.assertSame( "List should return node1 on getFirst()",
+                           this.list.getFirst(),
+                           this.node1 );
+        this.list.removeFirst();
+        Assert.assertSame( "List should return node2 on getFirst()",
+                           this.list.getFirst(),
+                           this.node2 );
+        this.list.removeFirst();
+        Assert.assertSame( "List should return node3 on getFirst()",
+                           this.list.getFirst(),
+                           this.node3 );
+        this.list.removeFirst();
+        Assert.assertNull( "Empty list should return null on getFirst()",
+                           this.list.getFirst() );
+    }
+
+    /*
+     * Test method for 'org.drools.util.LinkedList.removeLast()'
+     */
+    public void testRemoveLast() {
+        this.list.add( this.node1 );
+        this.list.add( this.node2 );
+        this.list.add( this.node3 );
+
+        Assert.assertSame( "List should return node1 on getLast()",
+                           this.list.getLast(),
+                           this.node3 );
+        this.list.removeLast();
+        Assert.assertSame( "List should return node2 on getLast()",
+                           this.list.getLast(),
+                           this.node2 );
+        this.list.removeLast();
+        Assert.assertSame( "List should return node3 on getLast()",
+                           this.list.getLast(),
+                           this.node1 );
+        this.list.removeLast();
+        Assert.assertNull( "Empty list should return null on getLast()",
+                           this.list.getLast() );
+    }
+
+    /*
+     * Test method for 'org.drools.util.LinkedList.isEmpty()'
+     */
+    public void testIsEmpty() {
+        Assert.assertTrue( "Empty list should return true on isEmpty()",
+                           this.list.isEmpty() );
+        this.list.add( this.node1 );
+        Assert.assertFalse( "Not empty list should return false on isEmpty()",
+                            this.list.isEmpty() );
+    }
+
+    /*
+     * Test method for 'org.drools.util.LinkedList.clear()'
+     */
+    public void testClear() {
+        this.list.add( this.node1 );
+        this.list.add( this.node2 );
+        this.list.add( this.node3 );
+
+        Assert.assertEquals( "List size should be 3",
+                             this.list.size(),
+                             3 );
+        this.list.clear();
+        Assert.assertEquals( "Empty list should have size 0",
+                             this.list.size(),
+                             0 );
+    }
+
+    /*
+     * Test method for 'org.drools.util.LinkedList.size()'
+     */
+    public void testSize() {
+        this.list.add( this.node1 );
+        Assert.assertEquals( "LinkedList should have 1 node",
+                             this.list.size(),
+                             1 );
+
+        this.list.add( this.node2 );
+        Assert.assertEquals( "LinkedList should have 2 nodes",
+                             this.list.size(),
+                             2 );
+
+        this.list.add( this.node3 );
+        Assert.assertEquals( "LinkedList should have 3 nodes",
+                             this.list.size(),
+                             3 );
+    }
+
+    public void testInsertAfter() {
+        try {
+            this.list.insertAfter( null,
+                                   this.node1 );
+        } catch (NullPointerException e) {
+            e.printStackTrace();
+            fail("Should NOT raise NPE!");
+        }
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/LongQueueable.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/LongQueueable.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/LongQueueable.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,35 @@
+package org.drools.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class LongQueueable extends BaseQueueable
+    implements
+    Comparable {
+    private final Long value;
+
+    public LongQueueable(final long value) {
+        this.value = new Long( value );
+    }
+
+    public int compareTo(final Object object) {
+        return this.value.compareTo( ((LongQueueable) object).value );
+    }
+
+    public String toString() {
+        return this.value.toString();
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/NaturalComparator.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/NaturalComparator.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/NaturalComparator.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,33 @@
+package org.drools.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Comparator;
+
+public final class NaturalComparator
+    implements
+    Comparator {
+    public static final NaturalComparator INSTANCE = new NaturalComparator();
+
+    private NaturalComparator() {
+    }
+
+    public int compare(final Object a,
+                       final Object b) {
+        return ((Comparable) a).compareTo( b );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/ObjectHashMapTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/ObjectHashMapTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/ObjectHashMapTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,135 @@
+package org.drools.util;
+
+import junit.framework.TestCase;
+
+import org.drools.Cheese;
+import org.drools.util.ObjectHashMap.ObjectEntry;
+
+public class ObjectHashMapTest extends TestCase {
+    public void testChechExistsFalse() {
+        final ObjectHashMap map = new ObjectHashMap();
+        final Cheese stilton = new Cheese( "stilton",
+                                           5 );
+        map.put( new Integer( 1 ),
+                 stilton,
+                 false );
+
+        Cheese c = (Cheese) map.get( new Integer( 1 ) );
+        assertSame( stilton,
+                    c );
+
+        // we haven't told the map to check if the key exists, so we should end up with two entries.
+        // the second one is nolonger reacheable
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           5 );
+        map.put( new Integer( 1 ),
+                 cheddar,
+                 false );
+        c = (Cheese) map.get( new Integer( 1 ) );
+        assertSame( cheddar,
+                    c );
+
+        Entry entry = map.getBucket( new Integer( 1 ) );
+        int size = 0;
+        while ( entry != null ) {
+            size++;
+            entry = entry.getNext();
+        }
+
+        assertEquals( 2,
+                      size );
+
+        // Check remove works, should leave one unreachable key
+        map.remove( new Integer( 1 ) );
+        entry = map.getBucket( new Integer( 1 ) );
+        size = 0;
+        while ( entry != null ) {
+            size++;
+            entry = entry.getNext();
+        }
+
+        assertEquals( 1,
+                      size );
+    }
+
+    public void testChechExistsTrue() {
+        final ObjectHashMap map = new ObjectHashMap();
+        final Cheese stilton = new Cheese( "stilton",
+                                           5 );
+        map.put( new Integer( 1 ),
+                 stilton,
+                 true );
+
+        Cheese c = (Cheese) map.get( new Integer( 1 ) );
+        assertSame( stilton,
+                    c );
+
+        // we haven't told the map to check if the key exists, so we should end up with two entries.
+        // the second one is nolonger reacheable
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           5 );
+        map.put( new Integer( 1 ),
+                 cheddar );
+        c = (Cheese) map.get( new Integer( 1 ) );
+        assertSame( cheddar,
+                    c );
+
+        Entry entry = map.getBucket( new Integer( 1 ) );
+        int size = 0;
+        while ( entry != null ) {
+            size++;
+            entry = entry.getNext();
+        }
+
+        assertEquals( 1,
+                      size );
+
+        // Check remove works
+        map.remove( new Integer( 1 ) );
+        entry = map.getBucket( new Integer( 1 ) );
+        size = 0;
+        while ( entry != null ) {
+            size++;
+            entry = entry.getNext();
+        }
+
+        assertEquals( 0,
+                      size );
+    }
+
+    public void testEmptyIterator() {
+        final ObjectHashMap map = new ObjectHashMap();
+        final Iterator it = map.iterator();
+        for ( ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next() ) {
+            fail( "Map is empty, there should be no iteration" );
+        }
+    }
+
+    public void testStringData() {
+        final ObjectHashMap map = new ObjectHashMap();
+        assertNotNull( map );
+        final int count = 1000;
+        for ( int idx = 0; idx < count; idx++ ) {
+            final String key = "key" + idx;
+            final String val = "value" + idx;
+            map.put( key,
+                     val );
+            assertEquals( val,
+                          map.get( key ) );
+        }
+    }
+
+    public void testIntegerData() {
+        final ObjectHashMap map = new ObjectHashMap();
+        assertNotNull( map );
+        final int count = 1000;
+        for ( int idx = 0; idx < count; idx++ ) {
+            final Integer key = new Integer( idx );
+            final Integer val = new Integer( idx );
+            map.put( key,
+                     val );
+            assertEquals( val,
+                          map.get( key ) );
+        }
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/ObjectHashMapTest2.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/ObjectHashMapTest2.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/ObjectHashMapTest2.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,210 @@
+package org.drools.util;
+
+import junit.framework.TestCase;
+import org.drools.util.ObjectHashMap;
+
+public class ObjectHashMapTest2 extends TestCase {
+
+    public ObjectHashMapTest2() {
+        super();
+    }
+
+    public void testJUHashmap() {
+        final java.util.HashMap map = new java.util.HashMap();
+        assertNotNull( map );
+        final int count = 1000;
+        for ( int idx = 0; idx < count; idx++ ) {
+            final String key = "key" + idx;
+            final String val = "value" + idx;
+            map.put( key,
+                     val );
+            assertEquals( val,
+                          map.get( key ) );
+        }
+    }
+
+    public void testStringData() {
+        final ObjectHashMap map = new ObjectHashMap();
+        assertNotNull( map );
+        final int count = 1000;
+        for ( int idx = 0; idx < count; idx++ ) {
+            final String key = "key" + idx;
+            final String val = "value" + idx;
+            map.put( key,
+                     val );
+            assertEquals( val,
+                          map.get( key ) );
+        }
+    }
+
+    public void testStringDataDupFalse() {
+        final ObjectHashMap map = new ObjectHashMap();
+        assertNotNull( map );
+        final int count = 10000;
+        for ( int idx = 0; idx < count; idx++ ) {
+            final String key = "key" + idx;
+            final String val = "value" + idx;
+            map.put( key,
+                     val,
+                     false );
+            assertEquals( val,
+                          map.get( key ) );
+        }
+    }
+
+    public void testIntegerData() {
+        final ObjectHashMap map = new ObjectHashMap();
+        assertNotNull( map );
+        final int count = 1000;
+        for ( int idx = 0; idx < count; idx++ ) {
+            final Integer key = new Integer( idx );
+            final Integer val = new Integer( idx );
+            map.put( key,
+                     val );
+            assertEquals( val,
+                          map.get( key ) );
+        }
+    }
+
+    public void testJUHashMap1() {
+        final int count = 100000;
+        final java.util.HashMap map = new java.util.HashMap();
+        assertNotNull( map );
+        final long start = System.currentTimeMillis();
+        for ( int idx = 0; idx < count; idx++ ) {
+            final String key = "key" + idx;
+            final String strval = "value" + idx;
+            map.put( key,
+                     strval );
+        }
+        final long end = System.currentTimeMillis();
+        System.out.println( "java.util.HashMap put(key,value) ET - " + ((end - start)) );
+    }
+
+    public void testStringData2() {
+        final int count = 100000;
+        final ObjectHashMap map = new ObjectHashMap();
+        assertNotNull( map );
+        final long start = System.currentTimeMillis();
+        for ( int idx = 0; idx < count; idx++ ) {
+            final String key = "key" + idx;
+            final String strval = "value" + idx;
+            map.put( key,
+                     strval );
+        }
+        final long end = System.currentTimeMillis();
+        System.out.println( "Custom ObjectHashMap put(key,value) ET - " + ((end - start)) );
+    }
+
+    public void testStringData3() {
+        final int count = 100000;
+        final ObjectHashMap map = new ObjectHashMap();
+        assertNotNull( map );
+        for ( int idx = 0; idx < count; idx++ ) {
+            final String key = "key" + idx;
+            final String strval = "value" + idx;
+            map.put( key,
+                     strval );
+        }
+        final long start = System.currentTimeMillis();
+        for ( int idx = 0; idx < count; idx++ ) {
+            final String key = "key" + idx;
+            map.get( key );
+        }
+        final long end = System.currentTimeMillis();
+        System.out.println( "Custom ObjectHashMap get(key) ET - " + ((end - start)) );
+    }
+
+    public void testJUHashMap2() {
+        final int count = 100000;
+        final java.util.HashMap map = new java.util.HashMap();
+        assertNotNull( map );
+        for ( int idx = 0; idx < count; idx++ ) {
+            final String key = "key" + idx;
+            final String strval = "value" + idx;
+            map.put( key,
+                     strval );
+        }
+        final long start = System.currentTimeMillis();
+        for ( int idx = 0; idx < count; idx++ ) {
+            final String key = "key" + idx;
+            map.get( key );
+        }
+        final long end = System.currentTimeMillis();
+        System.out.println( "java.util.HashMap get(key) ET - " + ((end - start)) );
+    }
+
+    public void testStringData4() {
+        final int count = 100000;
+        final ObjectHashMap map = new ObjectHashMap();
+        assertNotNull( map );
+        for ( int idx = 0; idx < count; idx++ ) {
+            final String key = "key" + idx;
+            final String strval = "value" + idx;
+            map.put( key,
+                     strval );
+        }
+        final long start = System.currentTimeMillis();
+        final org.drools.util.Iterator itr = map.iterator();
+        Object val = null;
+        while ( (val = itr.next()) != null ) {
+            val.hashCode();
+        }
+        final long end = System.currentTimeMillis();
+        System.out.println( "Custom ObjectHashMap iterate ET - " + ((end - start)) );
+    }
+
+    public void testJUHashMap3() {
+        final int count = 100000;
+        final java.util.HashMap map = new java.util.HashMap();
+        assertNotNull( map );
+        for ( int idx = 0; idx < count; idx++ ) {
+            final String key = "key" + idx;
+            final String strval = "value" + idx;
+            map.put( key,
+                     strval );
+        }
+        final long start = System.currentTimeMillis();
+        final java.util.Iterator itr = map.values().iterator();
+        while ( itr.hasNext() ) {
+            itr.next().hashCode();
+        }
+        final long end = System.currentTimeMillis();
+        System.out.println( "java.util.HashMap iterate ET - " + ((end - start)) );
+    }
+
+    public void testStringData5() {
+        final int count = 100000;
+        final ObjectHashMap map = new ObjectHashMap();
+        assertNotNull( map );
+        final long start = System.currentTimeMillis();
+        for ( int idx = 0; idx < count; idx++ ) {
+            final String key = "key" + idx;
+            final String strval = "value" + idx;
+            map.put( key,
+                     strval,
+                     false );
+        }
+        final long end = System.currentTimeMillis();
+        System.out.println( "Custom ObjectHashMap dup false ET - " + ((end - start)) );
+    }
+
+    public static void main(final String[] args) {
+        final ObjectHashMapTest2 test = new ObjectHashMapTest2();
+        final int loop = 5;
+        for ( int idx = 0; idx < loop; idx++ ) {
+            test.testIntegerData();
+            test.testStringData();
+            test.testJUHashmap();
+            test.testStringData2();
+            test.testJUHashMap1();
+            test.testStringData3();
+            test.testJUHashMap2();
+            test.testStringData4();
+            test.testJUHashMap3();
+            test.testStringData5();
+            test.testStringDataDupFalse();
+            System.out.println( " --------------- " );
+        }
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/PrimitiveLongMapTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/PrimitiveLongMapTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/PrimitiveLongMapTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,183 @@
+package org.drools.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Collection;
+
+import junit.framework.TestCase;
+
+public class PrimitiveLongMapTest extends TestCase {
+    public void testValues() {
+        final PrimitiveLongMap map = new PrimitiveLongMap();
+        assertNotNull( "MapNotNullTest ",
+                       map );
+
+        final Collection values = map.values();
+        assertNotNull( "ValuesNotNullTest ",
+                       values );
+        assertEquals( "ValuesZeroSizeTest ",
+                      0,
+                      values.size() );
+    }
+
+    public void testPaging() {
+        final PrimitiveLongMap map = new PrimitiveLongMap( 32,
+                                                           8 );
+
+        for ( int i = 0; i < 512; i++ ) {
+            final Integer value = new Integer( i );
+
+            final Object oldValue = map.put( i,
+                                             value );
+            assertNull( "OldValueNullTest ",
+                        oldValue );
+            assertEquals( "OldValueNullTest ",
+                          value,
+                          map.get( i ) );
+        }
+
+    }
+
+    public void testGetWithNegativeKeyReturnsNull() {
+        final PrimitiveLongMap map = new PrimitiveLongMap( 2,
+                                                           1 );
+
+        assertNull( map.get( -1 ) );
+    }
+
+    public void testRemoveWithNegativeReturnsNull() {
+        final PrimitiveLongMap map = new PrimitiveLongMap( 2,
+                                                           1 );
+
+        assertNull( map.remove( -1 ) );
+    }
+
+    public void testPutWithNegativeKeyThrowsIllegalArgumentException() {
+        final PrimitiveLongMap map = new PrimitiveLongMap( 2,
+                                                           1 );
+
+        try {
+            map.put( -1,
+                     new Object() );
+            fail();
+        } catch ( final IllegalArgumentException e ) {
+            // expected
+        }
+    }
+
+    /**
+     * this tests maxKey for gets and removes if ( key > this.maxKey || key < 0 ) {
+     * return null; }
+     * 
+     */
+    public void testMaxKey() {
+
+        final PrimitiveLongMap map = new PrimitiveLongMap( 8,
+                                                           4 );
+
+        // Test maxKey for key 0
+        map.put( 0,
+                 new Integer( 0 ) );
+
+        assertEquals( new Integer( 0 ),
+                      map.get( 0 ) );
+        assertNull( map.remove( 1 ) );
+        assertEquals( new Integer( 0 ),
+                      map.get( 0 ) );
+        assertNotNull( map.remove( 0 ) );
+        assertNull( map.get( 0 ) );
+
+        // Test maxKey for key 1
+        map.put( 1,
+                 new Integer( 1 ) );
+        assertEquals( new Integer( 1 ),
+                      map.get( 1 ) );
+        assertNull( map.remove( 2 ) );
+        assertEquals( new Integer( 1 ),
+                      map.get( 1 ) );
+        assertNotNull( map.remove( 1 ) );
+        assertNull( map.get( 1 ) );
+
+        // Test maxKey for key 127, an end to a page border
+        map.put( 127,
+                 new Integer( 127 ) );
+        assertEquals( new Integer( 127 ),
+                      map.get( 127 ) );
+        assertNull( map.remove( 128 ) );
+        assertEquals( new Integer( 127 ),
+                      map.get( 127 ) );
+        assertNotNull( map.remove( 127 ) );
+        assertNull( map.get( 127 ) );
+
+        // Test maxKey for key 128, a start to a new page
+        map.put( 128,
+                 new Integer( 128 ) );
+        assertEquals( new Integer( 128 ),
+                      map.get( 128 ) );
+        assertNull( map.remove( 129 ) );
+        assertEquals( new Integer( 128 ),
+                      map.get( 128 ) );
+        assertNotNull( map.remove( 128 ) );
+        assertNull( map.get( 128 ) );
+    }
+
+    public void testLastIndexBoundary() {
+        final PrimitiveLongMap map = new PrimitiveLongMap( 32,
+                                                           8 );
+        map.put( 8192,
+                 new Object() );
+        map.remove( 8192 );
+        map.put( 8192,
+                 new Object() );
+        map.put( 8191,
+                 new Object() );
+    }
+
+    public void testSize() {
+        final PrimitiveLongMap map = new PrimitiveLongMap( 32,
+                                                           8 );
+
+        final Object object = new Object();
+        map.put( 231,
+                 object );
+        final Object string = new Object();
+        map.put( 211,
+                 string );
+        map.put( 99822,
+                 null );
+        assertEquals( 3,
+                      map.size() );
+
+        map.put( 211,
+                 null );
+        map.put( 99822,
+                 string );
+        assertEquals( 3,
+                      map.size() );
+
+        map.remove( 211 );
+        assertEquals( 2,
+                      map.size() );
+        map.remove( 99822 );
+        assertEquals( 1,
+                      map.size() );
+
+        map.remove( 231 );
+        assertEquals( 0,
+                      map.size() );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/ShadowProxyUtilsTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/ShadowProxyUtilsTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/ShadowProxyUtilsTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,132 @@
+package org.drools.util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import junit.framework.TestCase;
+
+public class ShadowProxyUtilsTest extends TestCase {
+
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    public void testCloneList() {
+        List list = new ArrayList();
+        list.add( "a" );
+        list.add( "b" );
+
+        List clone = (List) ShadowProxyUtils.cloneObject( list );
+        assertEquals( list,
+                      clone );
+        assertNotSame( list,
+                       clone );
+    }
+
+    public void testCloneMap() {
+        Map map = new TreeMap();
+        map.put( "a",
+                 "a" );
+        map.put( "b",
+                 "b" );
+
+        Map clone = (Map) ShadowProxyUtils.cloneObject( map );
+        assertEquals( map,
+                      clone );
+        assertNotSame( map,
+                       clone );
+    }
+
+    public void testCloneArray() {
+        int[][] array = new int[][]{{0, 0}, {0, 1}, {1, 0}, {1, 1}};
+
+        int[][] clone = (int[][]) ShadowProxyUtils.cloneObject( array );
+        assertTrue( ArrayUtils.deepEquals( array,
+                                           clone ) );
+        assertNotSame( array,
+                       clone );
+    }
+
+    public void testCloneUnmodifiableSet() {
+        Set set = new HashSet();
+        set.add( "a" );
+        set.add( "b" );
+
+        Set unmod = Collections.unmodifiableSet( set );
+
+        Set clone = (Set) ShadowProxyUtils.cloneObject( unmod );
+        assertEquals( unmod,
+                      clone );
+        assertSame( unmod,
+                    clone );
+    }
+
+    public void testCloneUnmodifiableMap() {
+        Map map = new TreeMap();
+        map.put( "a",
+                 "a" );
+        map.put( "b",
+                 "b" );
+        Map unmod = Collections.unmodifiableMap( map );
+
+        Map clone = (Map) ShadowProxyUtils.cloneObject( unmod );
+        assertEquals( unmod,
+                      clone );
+        assertSame( unmod,
+                    clone );
+    }
+
+    public void testCloneEmptyList() {
+        List list = Collections.EMPTY_LIST;
+
+        List clone = (List) ShadowProxyUtils.cloneObject( list );
+        assertEquals( list,
+                      clone );
+        assertSame( list,
+                    clone );
+    }
+
+    public void testCloneEmptySet() {
+        Set set = Collections.EMPTY_SET;
+
+        Set clone = (Set) ShadowProxyUtils.cloneObject( set );
+        assertEquals( set,
+                      clone );
+        assertSame( set,
+                    clone );
+    }
+
+    public void testCloneEmptyMap() {
+        Map map = Collections.EMPTY_MAP;
+
+        Map clone = (Map) ShadowProxyUtils.cloneObject( map );
+        assertEquals( map,
+                      clone );
+        assertSame( map,
+                    clone );
+    }
+
+    public void testCloneRegularObject() {
+        // this is never supposed to happen,
+        // but we don't want the method to blow up if it happens
+        Object obj = new Object();
+
+        Object clone = (Object) ShadowProxyUtils.cloneObject( obj );
+        assertEquals( obj,
+                      clone );
+        assertSame( obj,
+                    clone );
+
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/AbstractClass.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/AbstractClass.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/AbstractClass.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,29 @@
+package org.drools.util.asm;
+
+public abstract class AbstractClass {
+    public String HTML;
+
+    public AbstractClass() {
+
+    }
+
+    public AbstractClass(final String HTML) {
+        super();
+        this.HTML = HTML;
+    }
+
+    /**
+     * @return the uRI
+     */
+    public String getHTML() {
+        return this.HTML;
+    }
+
+    /**
+     * @param uri the uRI to set
+     */
+    public void setHTML(final String HTML) {
+        this.HTML = HTML;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/BaseBean.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/BaseBean.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/BaseBean.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,36 @@
+package org.drools.util.asm;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class BaseBean {
+
+    private final String text   = "hola";
+    private int          number = 42;
+
+    public String getText() {
+        return this.text;
+    }
+
+    public int getNumber() {
+        return this.number;
+    }
+
+    public void setNumber(final int number) {
+        this.number = number;
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/BeanInherit.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/BeanInherit.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/BeanInherit.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,21 @@
+package org.drools.util.asm;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class BeanInherit extends BaseBean {
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/ClassFieldInspectorTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/ClassFieldInspectorTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/ClassFieldInspectorTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,293 @@
+package org.drools.util.asm;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.Iterator;
+import java.util.Map;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+public class ClassFieldInspectorTest extends TestCase {
+
+    public void testIt() throws Exception {
+        final ClassFieldInspector ext = new ClassFieldInspector( Person.class );
+        assertEquals( 7,
+                      ext.getPropertyGetters().size() );
+        assertEquals( "getAge",
+                      ((Method) ext.getPropertyGetters().get( 0 )).getName() );
+        assertEquals( "isHappy",
+                      ((Method) ext.getPropertyGetters().get( 1 )).getName() );
+        assertEquals( "getName",
+                      ((Method) ext.getPropertyGetters().get( 2 )).getName() );
+
+        final Map names = ext.getFieldNames();
+        assertNotNull( names );
+        assertEquals( 7,
+                      names.size() );
+        assertEquals( 0,
+                      ((Integer) names.get( "age" )).intValue() );
+        assertEquals( 1,
+                      ((Integer) names.get( "happy" )).intValue() );
+        assertEquals( 2,
+                      ((Integer) names.get( "name" )).intValue() );
+        assertNull( names.get( "nAme" ) );
+
+    }
+
+    public void testInterface() throws Exception {
+        final ClassFieldInspector ext = new ClassFieldInspector( TestInterface.class );
+        assertEquals( 2,
+                      ext.getPropertyGetters().size() );
+        assertEquals( "getSomething",
+                      ((Method) ext.getPropertyGetters().get( 0 )).getName() );
+        assertEquals( "getAnother",
+                      ((Method) ext.getPropertyGetters().get( 1 )).getName() );
+
+        final Map names = ext.getFieldNames();
+        assertNotNull( names );
+        assertEquals( 2,
+                      names.size() );
+        assertEquals( 0,
+                      ((Integer) names.get( "something" )).intValue() );
+        assertEquals( 1,
+                      ((Integer) names.get( "another" )).intValue() );
+
+    }
+
+    public void testAbstract() throws Exception {
+        final ClassFieldInspector ext = new ClassFieldInspector( TestAbstract.class );
+        assertEquals( 5,
+                      ext.getPropertyGetters().size() );
+        assertEquals( "getSomething",
+                      ((Method) ext.getPropertyGetters().get( 0 )).getName() );
+        assertEquals( "getAnother",
+                      ((Method) ext.getPropertyGetters().get( 1 )).getName() );
+
+        final Map names = ext.getFieldNames();
+        assertNotNull( names );
+        assertEquals( 5,
+                      names.size() );
+        assertEquals( 0,
+                      ((Integer) names.get( "something" )).intValue() );
+        assertEquals( 1,
+                      ((Integer) names.get( "another" )).intValue() );
+
+    }
+
+    public void testInheritedFields() throws Exception {
+        ClassFieldInspector ext = new ClassFieldInspector( BeanInherit.class );
+        assertEquals( 5,
+                      ext.getPropertyGetters().size() );
+
+        ext = new ClassFieldInspector( InterfaceChildImpl.class );
+        assertEquals( 8,
+                      ext.getPropertyGetters().size() );
+        // test inheritence from abstract class
+        assertEquals( 4,
+                      ((Integer) ext.getFieldNames().get( "HTML" )).intValue() );
+
+        // check normal field on child class
+        assertEquals( 1,
+                      ((Integer) ext.getFieldNames().get( "baz" )).intValue() );
+
+        // test inheritence from an interface
+        assertEquals( 3,
+                      ((Integer) ext.getFieldNames().get( "URI" )).intValue() );
+    }
+
+    public void testIntefaceInheritance() throws Exception {
+        final ClassFieldInspector ext = new ClassFieldInspector( InterfaceChild.class );
+        final Map fields = ext.getFieldNames();
+        assertTrue( fields.containsKey( "foo" ) );
+        assertTrue( fields.containsKey( "bar" ) );
+        assertTrue( fields.containsKey( "baz" ) );
+        assertTrue( fields.containsKey( "URI" ) );
+    }
+
+    public void testFieldIndexCalculation() {
+        try {
+            final ClassFieldInspector ext = new ClassFieldInspector( SubPerson.class );
+            final Map map = ext.getFieldNames();
+            final String[] fields = new String[map.size()];
+            for ( final Iterator i = map.entrySet().iterator(); i.hasNext(); ) {
+                final Map.Entry entry = (Map.Entry) i.next();
+                final String fieldName = (String) entry.getKey();
+                final int fieldIndex = ((Integer) entry.getValue()).intValue();
+                if ( fields[fieldIndex] == null ) {
+                    fields[fieldIndex] = fieldName;
+                } else {
+                    Assert.fail( "Duplicate index found for 2 fields: index[" + fieldIndex + "] = [" + fields[fieldIndex] + "] and [" + fieldName + "]" );
+                }
+            }
+        } catch ( final IOException e ) {
+            e.printStackTrace();
+            Assert.fail( "Unexpected exception thrown" );
+        }
+    }
+
+    public void testGetReturnTypes() throws Exception {
+        final ClassFieldInspector ext = new ClassFieldInspector( Person.class );
+        final Map types = ext.getFieldTypes();
+        assertNotNull( types );
+        assertEquals( boolean.class,
+                      types.get( "happy" ) );
+        assertEquals( int.class,
+                      types.get( "age" ) );
+        assertEquals( String.class,
+                      types.get( "name" ) );
+    }
+
+    public void testGetMethodForField() throws Exception {
+        final ClassFieldInspector ext = new ClassFieldInspector( Person.class );
+        final Map methods = ext.getGetterMethods();
+        assertNotNull( methods );
+        assertEquals( "isHappy",
+                      ((Method) methods.get( "happy" )).getName() );
+        assertEquals( "getName",
+                      ((Method) methods.get( "name" )).getName() );
+        // test case sensitive
+        assertNull( methods.get( "nAme" ) );
+        assertEquals( "getAge",
+                      ((Method) methods.get( "age" )).getName() );
+
+    }
+
+    public void testNonGetter() throws Exception {
+        final ClassFieldInspector ext = new ClassFieldInspector( NonGetter.class );
+        final Map methods = ext.getGetterMethods();
+        assertEquals( "getFoo",
+                      ((Method) methods.get( "foo" )).getName() );
+        assertEquals( 5,
+                      methods.size() );
+        assertTrue( ext.getFieldNames().containsKey( "foo" ) );
+        assertTrue( ext.getFieldNames().containsKey( "baz" ) );
+        assertEquals( String.class,
+                      ext.getFieldTypes().get( "foo" ) );
+
+    }
+
+    public void testWierdCapsForField() throws Exception {
+        final ClassFieldInspector ext = new ClassFieldInspector( Person.class );
+        final Map methods = ext.getGetterMethods();
+        assertEquals( "getURI",
+                      ((Method) methods.get( "URI" )).getName() );
+        assertEquals( 7,
+                      methods.size() );
+    }
+
+    static class NonGetter {
+
+        public int foo() {
+            return 42;
+        }
+
+        public String getFoo() {
+            return "foo";
+        }
+
+        public String baz() {
+            return "";
+        }
+
+        public void bas() {
+
+        }
+    }
+
+    static class Person {
+        public static String aStaticString;
+        private boolean      happy;
+        private String       name;
+        private int          age;
+        private String       URI;
+
+        static {
+            aStaticString = "A static String";
+        }
+
+        public int getAge() {
+            return this.age;
+        }
+
+        public void setAge(final int age) {
+            this.age = age;
+        }
+
+        public boolean isHappy() {
+            return this.happy;
+        }
+
+        public void setHappy(final boolean happy) {
+            this.happy = happy;
+        }
+
+        public String getName() {
+            return this.name;
+        }
+
+        public void setName(final String name) {
+            this.name = name;
+        }
+
+        //ignore this as it returns void type
+        public void getNotAGetter() {
+            return;
+        }
+
+        //ignore this as private
+        private boolean isBogus() {
+            return false;
+        }
+
+        //this will not show up as it is a getter that takes an argument
+        public String getAlsoBad(final String s) {
+            return "ignored";
+        }
+
+        //this should show up, as its a getter, but all CAPS
+        public String getURI() {
+            return this.URI;
+        }
+
+        public void setURI(final String URI) {
+            this.URI = URI;
+        }
+    }
+
+    static class SubPerson {
+        private int childField;
+
+        /**
+         * @return the childField
+         */
+        public int getChildField() {
+            return this.childField;
+        }
+
+        /**
+         * @param childField the childField to set
+         */
+        public void setChildField(final int childField) {
+            this.childField = childField;
+        }
+
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/InterfaceChild.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/InterfaceChild.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/InterfaceChild.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,26 @@
+package org.drools.util.asm;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public interface InterfaceChild
+    extends
+    InterfaceParent,
+    InterfaceParent2 {
+
+    public String getBar();
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/InterfaceChildImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/InterfaceChildImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/InterfaceChildImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,80 @@
+package org.drools.util.asm;
+
+public class InterfaceChildImpl extends AbstractClass
+    implements
+    InterfaceChild {
+
+    private String bar;
+    private int    foo;
+    private int    baz;
+    private String URI;
+
+    public InterfaceChildImpl(final String HTML,
+                              final String bar,
+                              final int foo,
+                              final int baz,
+                              final String uri) {
+        super( HTML );
+        this.bar = bar;
+        this.foo = foo;
+        this.baz = baz;
+        this.URI = uri;
+    }
+
+    /**
+     * @return the bar
+     */
+    public String getBar() {
+        return this.bar;
+    }
+
+    /**
+     * @param bar the bar to set
+     */
+    public void setBar(final String bar) {
+        this.bar = bar;
+    }
+
+    /**
+     * @return the baz
+     */
+    public int getBaz() {
+        return this.baz;
+    }
+
+    /**
+     * @param baz the baz to set
+     */
+    public void setBaz(final int baz) {
+        this.baz = baz;
+    }
+
+    /**
+     * @return the foo
+     */
+    public int getFoo() {
+        return this.foo;
+    }
+
+    /**
+     * @param foo the foo to set
+     */
+    public void setFoo(final int foo) {
+        this.foo = foo;
+    }
+
+    /**
+     * @return the uRI
+     */
+    public String getURI() {
+        return this.URI;
+    }
+
+    /**
+     * @param uri the uRI to set
+     */
+    public void setURI(final String uri) {
+        this.URI = uri;
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/InterfaceParent.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/InterfaceParent.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/InterfaceParent.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,23 @@
+package org.drools.util.asm;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public interface InterfaceParent {
+
+    public int getFoo();
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/InterfaceParent2.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/InterfaceParent2.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/InterfaceParent2.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,25 @@
+package org.drools.util.asm;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public interface InterfaceParent2 {
+
+    public int getBaz();
+
+    public String getURI();
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/MethodCompareA.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/MethodCompareA.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/MethodCompareA.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,25 @@
+package org.drools.util.asm;
+
+public class MethodCompareA {
+
+    public boolean evaluate(final String foo) {
+        if ( foo == null || foo.startsWith( "42" ) ) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public boolean askew(final Integer a) {
+        return false;
+    }
+
+    public boolean evaluate2(final String foo) {
+        if ( foo == null || foo.startsWith( "43" ) ) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/MethodCompareB.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/MethodCompareB.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/MethodCompareB.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,14 @@
+package org.drools.util.asm;
+
+public class MethodCompareB {
+
+    public boolean evaluate(final String foox) {
+        if ( foox == null || foox.startsWith( "42" ) ) {
+
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/MethodComparerTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/MethodComparerTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/MethodComparerTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,67 @@
+package org.drools.util.asm;
+
+import java.io.InputStream;
+
+import junit.framework.TestCase;
+
+import org.drools.asm.ClassReader;
+
+public class MethodComparerTest extends TestCase {
+
+    public void testMethodCompare() throws Exception {
+        final MethodComparator comp = new MethodComparator();
+        boolean result = comp.equivalent( "evaluate",
+                                          new ClassReader( getClassData( MethodCompareA.class ) ),
+                                          "evaluate",
+                                          new ClassReader( getClassData( MethodCompareB.class ) ) );
+        assertEquals( true,
+                      result );
+
+        result = comp.equivalent( "evaluate",
+                                  new ClassReader( getClassData( MethodCompareA.class ) ),
+                                  "evaluate2",
+                                  new ClassReader( getClassData( MethodCompareA.class ) ) );
+        assertEquals( false,
+                      result );
+
+        result = comp.equivalent( "evaluate",
+                                  new ClassReader( getClassData( MethodCompareB.class ) ),
+                                  "evaluate2",
+                                  new ClassReader( getClassData( MethodCompareA.class ) ) );
+        assertEquals( false,
+                      result );
+
+        result = comp.equivalent( "evaluate",
+                                  new ClassReader( getClassData( MethodCompareB.class ) ),
+                                  "evaluate",
+                                  new ClassReader( getClassData( MethodCompareA.class ) ) );
+        assertEquals( true,
+                      result );
+
+        result = comp.equivalent( "evaluate",
+                                  new ClassReader( getClassData( MethodCompareA.class ) ),
+                                  "evaluate",
+                                  new ClassReader( getClassData( MethodCompareA.class ) ) );
+        assertEquals( true,
+                      result );
+
+        result = comp.equivalent( "evaluate",
+                                  new ClassReader( getClassData( MethodCompareA.class ) ),
+                                  "askew",
+                                  new ClassReader( getClassData( MethodCompareA.class ) ) );
+        assertEquals( false,
+                      result );
+
+    }
+
+    private InputStream getClassData(final Class clazz) {
+        final String name = getResourcePath( clazz );
+        return clazz.getResourceAsStream( name );
+    }
+
+    private String getResourcePath(final Class clazz) {
+        return "/" + clazz.getName().replaceAll( "\\.",
+                                                 "/" ) + ".class";
+    }
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestAbstract.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestAbstract.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestAbstract.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,27 @@
+package org.drools.util.asm;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public abstract class TestAbstract {
+
+    public abstract String getSomething();
+
+    public int getAnother() {
+        return 42;
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestAbstractImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestAbstractImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestAbstractImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,25 @@
+package org.drools.util.asm;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class TestAbstractImpl extends TestAbstract {
+
+    public String getSomething() {
+        return "foo";
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestBean.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestBean.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestBean.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,70 @@
+package org.drools.util.asm;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class TestBean {
+
+    private String   something;
+    private int      number;
+    private boolean  blah;
+    private Object[] objArray;
+
+    public boolean isBlah() {
+        return this.blah;
+    }
+
+    public void setBlah(final boolean blah) {
+        this.blah = blah;
+    }
+
+    public int getNumber() {
+        return this.number;
+    }
+
+    public void setNumber(final int number) {
+        this.number = number;
+    }
+
+    public String getSomething() {
+        return this.something;
+    }
+
+    public void setSomething(final String something) {
+        this.something = something;
+    }
+
+    public String fooBar() {
+        return "fooBar";
+    }
+
+    public long getLongField() {
+        return 424242;
+    }
+
+    public Long getOtherLongField() {
+        return new Long( 42424242 );
+    }
+
+    public Object[] getObjArray() {
+        return this.objArray;
+    }
+
+    public void setObjArray(final Object[] objArray) {
+        this.objArray = objArray;
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestInterface.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestInterface.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestInterface.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,25 @@
+package org.drools.util.asm;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public interface TestInterface {
+
+    public String getSomething();
+
+    public int getAnother();
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestInterfaceImpl.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestInterfaceImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestInterfaceImpl.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,31 @@
+package org.drools.util.asm;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class TestInterfaceImpl
+    implements
+    TestInterface {
+
+    public String getSomething() {
+        return "foo";
+    }
+
+    public int getAnother() {
+        return 42;
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestObject.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestObject.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/util/asm/TestObject.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,87 @@
+package org.drools.util.asm;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.math.BigDecimal;
+
+public class TestObject {
+
+    private String     personName;
+    private int        personAge;
+    private BigDecimal personWeight;
+    private boolean    happy;
+    private long       someLong;
+    private char       someChar;
+    private short      someShort;
+
+    public boolean isHappy() {
+        return this.happy;
+    }
+
+    public void setHappy(final boolean happy) {
+        this.happy = happy;
+    }
+
+    public int getPersonAge() {
+        return this.personAge;
+    }
+
+    public void setPersonAge(final int personAge) {
+        this.personAge = personAge;
+    }
+
+    public String getPersonName() {
+        return this.personName;
+    }
+
+    public void setPersonName(final String personName) {
+        this.personName = personName;
+    }
+
+    public BigDecimal getPersonWeight() {
+        return this.personWeight;
+    }
+
+    public void setPersonWeight(final BigDecimal personWeight) {
+        this.personWeight = personWeight;
+    }
+
+    public char getSomeChar() {
+        return this.someChar;
+    }
+
+    public void setSomeChar(final char someChar) {
+        this.someChar = someChar;
+    }
+
+    public long getSomeLong() {
+        return this.someLong;
+    }
+
+    public void setSomeLong(final long someLong) {
+        this.someLong = someLong;
+    }
+
+    public short getSomeShort() {
+        return this.someShort;
+    }
+
+    public void setSomeShort(final short someShort) {
+        this.someShort = someShort;
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/EndNodeInstanceTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/EndNodeInstanceTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/EndNodeInstanceTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,51 @@
+package org.drools.workflow.instance.node;
+
+
+import junit.framework.TestCase;
+
+import org.drools.RuleBase;
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuleBaseFactory;
+import org.drools.StatefulSession;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.process.instance.ProcessInstance;
+import org.drools.ruleflow.instance.RuleFlowProcessInstance;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.impl.ConnectionImpl;
+import org.drools.workflow.core.impl.WorkflowProcessImpl;
+import org.drools.workflow.core.node.EndNode;
+
+public class EndNodeInstanceTest extends TestCase {
+    
+    public void testEndNode() {
+        RuleBaseConfiguration conf = new RuleBaseConfiguration();
+        RuleBase ruleBase = RuleBaseFactory.newRuleBase( conf );
+        StatefulSession session = ruleBase.newStatefulSession();        
+        
+        MockNode mockNode = new MockNode();        
+        MockNodeInstanceFactory factory = new MockNodeInstanceFactory( new MockNodeInstance( mockNode ) );
+        conf.getProcessNodeInstanceFactoryRegistry().register(  mockNode.getClass(), factory );
+        
+        WorkflowProcessImpl process = new WorkflowProcessImpl(); 
+        
+        Node endNode = new EndNode();  
+        endNode.setId( 1 );
+        endNode.setName( "end node" );        
+                            
+        mockNode.setId( 2 );
+        new ConnectionImpl(mockNode, Node.CONNECTION_DEFAULT_TYPE, endNode, Node.CONNECTION_DEFAULT_TYPE);
+        
+        process.addNode( mockNode );
+        process.addNode( endNode );
+                
+        RuleFlowProcessInstance processInstance = new RuleFlowProcessInstance();   
+        processInstance.setState( ProcessInstance.STATE_ACTIVE );
+        processInstance.setProcess( process );
+        processInstance.setWorkingMemory( (InternalWorkingMemory) session );
+        
+        MockNodeInstance mockNodeInstance = ( MockNodeInstance ) processInstance.getNodeInstance( mockNode );
+        
+        mockNodeInstance.triggerCompleted();
+        assertEquals( ProcessInstance.STATE_COMPLETED, processInstance.getState() );                               
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/MockNode.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/MockNode.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/MockNode.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,9 @@
+package org.drools.workflow.instance.node;
+
+import org.drools.workflow.core.node.SequenceNode;
+
+public class MockNode extends SequenceNode {
+
+    private static final long serialVersionUID = 400L;
+
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/MockNodeInstance.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/MockNodeInstance.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/MockNodeInstance.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,67 @@
+/**
+ * 
+ */
+package org.drools.workflow.instance.node;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.workflow.core.Node;
+import org.drools.workflow.instance.NodeInstance;
+import org.drools.workflow.instance.impl.NodeInstanceImpl;
+
+public class MockNodeInstance extends NodeInstanceImpl {
+    
+    private static final long serialVersionUID = 400L;
+
+    private Map<String, List<NodeInstance>> triggers = new HashMap<String, List<NodeInstance>>();
+    private MockNode mockNode;
+    
+    public MockNodeInstance(MockNode mockNode) {
+        this.mockNode = mockNode;
+    }
+    
+    public Node getNode() {
+        return mockNode;
+    }
+    
+    public MockNode getMockNode() {
+        return mockNode;
+    }
+    
+    public void internalTrigger(NodeInstance from, String type) {
+        if (type == null) {
+            throw new IllegalArgumentException(
+                "Trigger type is null!");
+        }
+        List<NodeInstance> list = triggers.get(type);
+        if (list == null) {
+            list = new ArrayList<NodeInstance>();
+            triggers.put(type, list);
+        }
+        list.add(from);
+    }
+    
+    public Map<String, List<NodeInstance>> getTriggers() {
+        return triggers;
+    }      
+    
+    public int hashCode() {
+        return (int) getNodeId();
+    }
+    
+    public boolean equals(Object object) {
+        if ( object == null || (!( object instanceof MockNodeInstance ) )) {
+            return false;
+        }
+        MockNodeInstance other = ( MockNodeInstance ) object;
+        return getNodeId() == other.getNodeId();
+    }        
+    
+    public void triggerCompleted() {        
+        getNodeInstanceContainer().removeNodeInstance(this);
+        getNodeInstanceContainer().getNodeInstance(getMockNode().getTo().getTo()).trigger(this, getMockNode().getTo().getToType());
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/MockNodeInstanceFactory.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/MockNodeInstanceFactory.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/MockNodeInstanceFactory.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,27 @@
+/**
+ * 
+ */
+package org.drools.workflow.instance.node;
+
+import org.drools.workflow.core.Node;
+import org.drools.workflow.instance.NodeInstance;
+import org.drools.workflow.instance.NodeInstanceContainer;
+import org.drools.workflow.instance.WorkflowProcessInstance;
+import org.drools.workflow.instance.impl.NodeInstanceFactory;
+
+public class MockNodeInstanceFactory implements NodeInstanceFactory {
+    
+    private MockNodeInstance instance;
+    
+    public MockNodeInstanceFactory(MockNodeInstance instance) {
+        this.instance = instance;
+    }
+    
+    public MockNodeInstance getMockNodeInstance() {
+        return this.instance;
+    }
+
+    public NodeInstance getNodeInstance(Node node, WorkflowProcessInstance processInstance, NodeInstanceContainer nodeInstanceContainer) {
+        return instance;
+    }        
+}
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/ProcessNodeInstanceFactoryTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/ProcessNodeInstanceFactoryTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/ProcessNodeInstanceFactoryTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,29 @@
+package org.drools.workflow.instance.node;
+
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+import org.drools.RuleBaseConfiguration;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.node.ActionNode;
+import org.drools.workflow.instance.impl.NodeInstanceFactoryRegistry;
+import org.drools.workflow.instance.impl.factory.CreateNewNodeFactory;
+
+public class ProcessNodeInstanceFactoryTest extends TestCase {
+    
+    public void testDefaultEntries() throws Exception {
+        RuleBaseConfiguration conf = new RuleBaseConfiguration();
+        NodeInstanceFactoryRegistry registry = conf.getProcessNodeInstanceFactoryRegistry();
+        Node node = new ActionNode();
+        assertEquals( CreateNewNodeFactory.class, registry.getProcessNodeInstanceFactory( node ).getClass() );       
+    }
+    
+    public void testDiscoveredEntry() {
+        Properties properties = new Properties(); 
+        properties.put( "processNodeInstanceFactoryRegistry", "mockProcessNodeInstanceFactory.conf" );        
+        RuleBaseConfiguration conf = new RuleBaseConfiguration( properties );
+        NodeInstanceFactoryRegistry registry = conf.getProcessNodeInstanceFactoryRegistry();
+        assertEquals( MockNodeInstanceFactory.class, registry.getProcessNodeInstanceFactory( new MockNode() ).getClass() );
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/StartNodeInstanceTest.java
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/StartNodeInstanceTest.java	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/java/org/drools/workflow/instance/node/StartNodeInstanceTest.java	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,59 @@
+package org.drools.workflow.instance.node;
+
+
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.drools.RuleBase;
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuleBaseFactory;
+import org.drools.StatefulSession;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.process.instance.ProcessInstance;
+import org.drools.ruleflow.core.RuleFlowProcess;
+import org.drools.ruleflow.instance.RuleFlowProcessInstance;
+import org.drools.workflow.core.Node;
+import org.drools.workflow.core.impl.ConnectionImpl;
+import org.drools.workflow.core.node.StartNode;
+import org.drools.workflow.instance.NodeInstance;
+
+public class StartNodeInstanceTest extends TestCase {
+    
+    public void testStartNode() {
+        
+        RuleBaseConfiguration conf = new RuleBaseConfiguration();
+        RuleBase ruleBase = RuleBaseFactory.newRuleBase( conf );
+        StatefulSession session = ruleBase.newStatefulSession();        
+        
+        MockNode mockNode = new MockNode();
+        MockNodeInstanceFactory mockNodeFactory = new MockNodeInstanceFactory( new MockNodeInstance( mockNode ) );
+        conf.getProcessNodeInstanceFactoryRegistry().register( mockNode.getClass(), mockNodeFactory );
+        
+        RuleFlowProcess process = new RuleFlowProcess(); 
+        
+        Node startNode = new StartNode();  
+        startNode.setId( 1 );
+        startNode.setName( "start node" );                
+                            
+        mockNode.setId( 2 );
+        new ConnectionImpl(startNode, Node.CONNECTION_DEFAULT_TYPE, mockNode, Node.CONNECTION_DEFAULT_TYPE);
+        
+        process.addNode( startNode );
+        process.addNode( mockNode );
+                
+        RuleFlowProcessInstance processInstance = new RuleFlowProcessInstance();   
+        processInstance.setProcess( process );
+        processInstance.setWorkingMemory( (InternalWorkingMemory) session );              
+        
+        assertEquals(  ProcessInstance.STATE_PENDING, processInstance.getState() );
+        processInstance.start();        
+        assertEquals(  ProcessInstance.STATE_ACTIVE, processInstance.getState() );
+        
+        MockNodeInstance mockNodeInstance = mockNodeFactory.getMockNodeInstance();
+        List<NodeInstance> triggeredBy = mockNodeInstance.getTriggers().get(Node.CONNECTION_DEFAULT_TYPE);
+        assertNotNull(triggeredBy);
+        assertEquals(1, triggeredBy.size());
+        assertSame(startNode.getId(), triggeredBy.get(0).getNodeId());
+    }
+}

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/META-INF/mockProcessNodeInstanceFactory.conf
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/META-INF/mockProcessNodeInstanceFactory.conf	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/META-INF/mockProcessNodeInstanceFactory.conf	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,8 @@
+// we use MVEL to configure our nodes, simply populate a map, which will be added to the main registry
+import org.drools.workflow.instance.node.MockNode;       
+import org.drools.workflow.instance.node.MockNodeInstance;
+import org.drools.workflow.instance.node.MockNodeInstanceFactory;
+
+[
+    MockNode : new MockNodeInstanceFactory(  new MockNodeInstance(  new MockNode() ) )
+]

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/correct_processTree1.dat
===================================================================
(Binary files differ)


Property changes on: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/correct_processTree1.dat
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/correct_transform1.dat
===================================================================
(Binary files differ)


Property changes on: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/correct_transform1.dat
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners128.dat
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners128.dat	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners128.dat	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,440 @@
+(guest (name 1) (sex m) (hobby h2) )
+(guest (name 1) (sex m) (hobby h3) )
+(guest (name 1) (sex m) (hobby h1) )
+(guest (name 1) (sex m) (hobby h4) )
+(guest (name 1) (sex m) (hobby h5) )
+(guest (name 2) (sex f) (hobby h3) )
+(guest (name 2) (sex f) (hobby h2) )
+(guest (name 2) (sex f) (hobby h1) )
+(guest (name 2) (sex f) (hobby h4) )
+(guest (name 2) (sex f) (hobby h5) )
+(guest (name 3) (sex f) (hobby h5) )
+(guest (name 3) (sex f) (hobby h4) )
+(guest (name 3) (sex f) (hobby h2) )
+(guest (name 4) (sex m) (hobby h3) )
+(guest (name 4) (sex m) (hobby h2) )
+(guest (name 4) (sex m) (hobby h1) )
+(guest (name 4) (sex m) (hobby h4) )
+(guest (name 5) (sex m) (hobby h2) )
+(guest (name 5) (sex m) (hobby h5) )
+(guest (name 5) (sex m) (hobby h3) )
+(guest (name 6) (sex f) (hobby h1) )
+(guest (name 6) (sex f) (hobby h4) )
+(guest (name 6) (sex f) (hobby h2) )
+(guest (name 6) (sex f) (hobby h5) )
+(guest (name 6) (sex f) (hobby h3) )
+(guest (name 7) (sex f) (hobby h1) )
+(guest (name 7) (sex f) (hobby h2) )
+(guest (name 7) (sex f) (hobby h3) )
+(guest (name 7) (sex f) (hobby h5) )
+(guest (name 8) (sex m) (hobby h3) )
+(guest (name 8) (sex m) (hobby h5) )
+(guest (name 9) (sex m) (hobby h3) )
+(guest (name 9) (sex m) (hobby h5) )
+(guest (name 9) (sex m) (hobby h2) )
+(guest (name 9) (sex m) (hobby h4) )
+(guest (name 10) (sex m) (hobby h2) )
+(guest (name 10) (sex m) (hobby h3) )
+(guest (name 10) (sex m) (hobby h4) )
+(guest (name 10) (sex m) (hobby h5) )
+(guest (name 10) (sex m) (hobby h1) )
+(guest (name 11) (sex m) (hobby h2) )
+(guest (name 11) (sex m) (hobby h4) )
+(guest (name 11) (sex m) (hobby h5) )
+(guest (name 11) (sex m) (hobby h1) )
+(guest (name 12) (sex f) (hobby h3) )
+(guest (name 12) (sex f) (hobby h5) )
+(guest (name 12) (sex f) (hobby h2) )
+(guest (name 13) (sex f) (hobby h5) )
+(guest (name 13) (sex f) (hobby h1) )
+(guest (name 14) (sex m) (hobby h3) )
+(guest (name 14) (sex m) (hobby h5) )
+(guest (name 14) (sex m) (hobby h1) )
+(guest (name 14) (sex m) (hobby h4) )
+(guest (name 15) (sex m) (hobby h5) )
+(guest (name 15) (sex m) (hobby h2) )
+(guest (name 15) (sex m) (hobby h1) )
+(guest (name 15) (sex m) (hobby h3) )
+(guest (name 15) (sex m) (hobby h4) )
+(guest (name 16) (sex m) (hobby h2) )
+(guest (name 16) (sex m) (hobby h5) )
+(guest (name 16) (sex m) (hobby h4) )
+(guest (name 17) (sex m) (hobby h4) )
+(guest (name 17) (sex m) (hobby h3) )
+(guest (name 18) (sex f) (hobby h2) )
+(guest (name 18) (sex f) (hobby h4) )
+(guest (name 18) (sex f) (hobby h5) )
+(guest (name 18) (sex f) (hobby h1) )
+(guest (name 19) (sex m) (hobby h5) )
+(guest (name 19) (sex m) (hobby h2) )
+(guest (name 20) (sex m) (hobby h2) )
+(guest (name 20) (sex m) (hobby h3) )
+(guest (name 21) (sex m) (hobby h4) )
+(guest (name 21) (sex m) (hobby h3) )
+(guest (name 21) (sex m) (hobby h2) )
+(guest (name 21) (sex m) (hobby h1) )
+(guest (name 22) (sex m) (hobby h1) )
+(guest (name 22) (sex m) (hobby h2) )
+(guest (name 22) (sex m) (hobby h4) )
+(guest (name 23) (sex f) (hobby h4) )
+(guest (name 23) (sex f) (hobby h5) )
+(guest (name 23) (sex f) (hobby h2) )
+(guest (name 24) (sex f) (hobby h4) )
+(guest (name 24) (sex f) (hobby h3) )
+(guest (name 24) (sex f) (hobby h2) )
+(guest (name 24) (sex f) (hobby h1) )
+(guest (name 24) (sex f) (hobby h5) )
+(guest (name 25) (sex m) (hobby h4) )
+(guest (name 25) (sex m) (hobby h5) )
+(guest (name 26) (sex m) (hobby h1) )
+(guest (name 26) (sex m) (hobby h2) )
+(guest (name 27) (sex m) (hobby h3) )
+(guest (name 27) (sex m) (hobby h5) )
+(guest (name 27) (sex m) (hobby h2) )
+(guest (name 28) (sex f) (hobby h4) )
+(guest (name 28) (sex f) (hobby h1) )
+(guest (name 28) (sex f) (hobby h3) )
+(guest (name 28) (sex f) (hobby h2) )
+(guest (name 28) (sex f) (hobby h5) )
+(guest (name 29) (sex f) (hobby h3) )
+(guest (name 29) (sex f) (hobby h5) )
+(guest (name 30) (sex m) (hobby h2) )
+(guest (name 30) (sex m) (hobby h1) )
+(guest (name 31) (sex m) (hobby h3) )
+(guest (name 31) (sex m) (hobby h1) )
+(guest (name 31) (sex m) (hobby h4) )
+(guest (name 32) (sex f) (hobby h2) )
+(guest (name 32) (sex f) (hobby h1) )
+(guest (name 32) (sex f) (hobby h5) )
+(guest (name 33) (sex f) (hobby h5) )
+(guest (name 33) (sex f) (hobby h4) )
+(guest (name 34) (sex m) (hobby h4) )
+(guest (name 34) (sex m) (hobby h5) )
+(guest (name 34) (sex m) (hobby h2) )
+(guest (name 35) (sex f) (hobby h3) )
+(guest (name 35) (sex f) (hobby h1) )
+(guest (name 35) (sex f) (hobby h4) )
+(guest (name 35) (sex f) (hobby h5) )
+(guest (name 35) (sex f) (hobby h2) )
+(guest (name 36) (sex m) (hobby h1) )
+(guest (name 36) (sex m) (hobby h4) )
+(guest (name 36) (sex m) (hobby h2) )
+(guest (name 36) (sex m) (hobby h3) )
+(guest (name 37) (sex f) (hobby h4) )
+(guest (name 37) (sex f) (hobby h2) )
+(guest (name 37) (sex f) (hobby h1) )
+(guest (name 38) (sex f) (hobby h3) )
+(guest (name 38) (sex f) (hobby h1) )
+(guest (name 38) (sex f) (hobby h2) )
+(guest (name 38) (sex f) (hobby h4) )
+(guest (name 39) (sex m) (hobby h5) )
+(guest (name 39) (sex m) (hobby h2) )
+(guest (name 40) (sex m) (hobby h2) )
+(guest (name 40) (sex m) (hobby h3) )
+(guest (name 41) (sex f) (hobby h5) )
+(guest (name 41) (sex f) (hobby h3) )
+(guest (name 42) (sex m) (hobby h5) )
+(guest (name 42) (sex m) (hobby h4) )
+(guest (name 43) (sex m) (hobby h3) )
+(guest (name 43) (sex m) (hobby h4) )
+(guest (name 43) (sex m) (hobby h5) )
+(guest (name 44) (sex f) (hobby h2) )
+(guest (name 44) (sex f) (hobby h4) )
+(guest (name 44) (sex f) (hobby h3) )
+(guest (name 44) (sex f) (hobby h1) )
+(guest (name 45) (sex m) (hobby h2) )
+(guest (name 45) (sex m) (hobby h4) )
+(guest (name 46) (sex m) (hobby h4) )
+(guest (name 46) (sex m) (hobby h1) )
+(guest (name 46) (sex m) (hobby h5) )
+(guest (name 47) (sex m) (hobby h2) )
+(guest (name 47) (sex m) (hobby h5) )
+(guest (name 47) (sex m) (hobby h4) )
+(guest (name 48) (sex f) (hobby h3) )
+(guest (name 48) (sex f) (hobby h1) )
+(guest (name 49) (sex m) (hobby h1) )
+(guest (name 49) (sex m) (hobby h5) )
+(guest (name 49) (sex m) (hobby h4) )
+(guest (name 49) (sex m) (hobby h3) )
+(guest (name 49) (sex m) (hobby h2) )
+(guest (name 50) (sex m) (hobby h2) )
+(guest (name 50) (sex m) (hobby h4) )
+(guest (name 50) (sex m) (hobby h3) )
+(guest (name 51) (sex m) (hobby h1) )
+(guest (name 51) (sex m) (hobby h2) )
+(guest (name 51) (sex m) (hobby h5) )
+(guest (name 51) (sex m) (hobby h4) )
+(guest (name 52) (sex f) (hobby h5) )
+(guest (name 52) (sex f) (hobby h3) )
+(guest (name 52) (sex f) (hobby h1) )
+(guest (name 52) (sex f) (hobby h4) )
+(guest (name 53) (sex f) (hobby h5) )
+(guest (name 53) (sex f) (hobby h1) )
+(guest (name 53) (sex f) (hobby h4) )
+(guest (name 53) (sex f) (hobby h2) )
+(guest (name 53) (sex f) (hobby h3) )
+(guest (name 54) (sex f) (hobby h1) )
+(guest (name 54) (sex f) (hobby h3) )
+(guest (name 55) (sex m) (hobby h2) )
+(guest (name 55) (sex m) (hobby h4) )
+(guest (name 56) (sex m) (hobby h2) )
+(guest (name 56) (sex m) (hobby h3) )
+(guest (name 57) (sex f) (hobby h2) )
+(guest (name 57) (sex f) (hobby h1) )
+(guest (name 57) (sex f) (hobby h4) )
+(guest (name 58) (sex m) (hobby h5) )
+(guest (name 58) (sex m) (hobby h3) )
+(guest (name 58) (sex m) (hobby h2) )
+(guest (name 58) (sex m) (hobby h1) )
+(guest (name 58) (sex m) (hobby h4) )
+(guest (name 59) (sex f) (hobby h2) )
+(guest (name 59) (sex f) (hobby h3) )
+(guest (name 59) (sex f) (hobby h5) )
+(guest (name 60) (sex f) (hobby h4) )
+(guest (name 60) (sex f) (hobby h2) )
+(guest (name 60) (sex f) (hobby h3) )
+(guest (name 60) (sex f) (hobby h5) )
+(guest (name 61) (sex m) (hobby h1) )
+(guest (name 61) (sex m) (hobby h2) )
+(guest (name 61) (sex m) (hobby h4) )
+(guest (name 61) (sex m) (hobby h3) )
+(guest (name 62) (sex f) (hobby h3) )
+(guest (name 62) (sex f) (hobby h2) )
+(guest (name 62) (sex f) (hobby h5) )
+(guest (name 62) (sex f) (hobby h4) )
+(guest (name 62) (sex f) (hobby h1) )
+(guest (name 63) (sex f) (hobby h2) )
+(guest (name 63) (sex f) (hobby h3) )
+(guest (name 63) (sex f) (hobby h4) )
+(guest (name 63) (sex f) (hobby h1) )
+(guest (name 63) (sex f) (hobby h5) )
+(guest (name 64) (sex f) (hobby h2) )
+(guest (name 64) (sex f) (hobby h4) )
+(guest (name 64) (sex f) (hobby h1) )
+(guest (name 64) (sex f) (hobby h5) )
+(guest (name 64) (sex f) (hobby h3) )
+(guest (name 65) (sex m) (hobby h5) )
+(guest (name 65) (sex m) (hobby h3) )
+(guest (name 65) (sex m) (hobby h2) )
+(guest (name 65) (sex m) (hobby h1) )
+(guest (name 65) (sex m) (hobby h4) )
+(guest (name 66) (sex f) (hobby h5) )
+(guest (name 66) (sex f) (hobby h3) )
+(guest (name 66) (sex f) (hobby h4) )
+(guest (name 67) (sex f) (hobby h1) )
+(guest (name 67) (sex f) (hobby h4) )
+(guest (name 68) (sex m) (hobby h4) )
+(guest (name 68) (sex m) (hobby h2) )
+(guest (name 68) (sex m) (hobby h1) )
+(guest (name 68) (sex m) (hobby h5) )
+(guest (name 69) (sex m) (hobby h3) )
+(guest (name 69) (sex m) (hobby h4) )
+(guest (name 69) (sex m) (hobby h1) )
+(guest (name 70) (sex f) (hobby h3) )
+(guest (name 70) (sex f) (hobby h5) )
+(guest (name 70) (sex f) (hobby h1) )
+(guest (name 70) (sex f) (hobby h4) )
+(guest (name 70) (sex f) (hobby h2) )
+(guest (name 71) (sex m) (hobby h3) )
+(guest (name 71) (sex m) (hobby h1) )
+(guest (name 71) (sex m) (hobby h4) )
+(guest (name 72) (sex m) (hobby h4) )
+(guest (name 72) (sex m) (hobby h3) )
+(guest (name 72) (sex m) (hobby h1) )
+(guest (name 73) (sex f) (hobby h4) )
+(guest (name 73) (sex f) (hobby h1) )
+(guest (name 73) (sex f) (hobby h3) )
+(guest (name 74) (sex f) (hobby h1) )
+(guest (name 74) (sex f) (hobby h4) )
+(guest (name 74) (sex f) (hobby h2) )
+(guest (name 74) (sex f) (hobby h5) )
+(guest (name 74) (sex f) (hobby h3) )
+(guest (name 75) (sex f) (hobby h4) )
+(guest (name 75) (sex f) (hobby h2) )
+(guest (name 76) (sex f) (hobby h5) )
+(guest (name 76) (sex f) (hobby h4) )
+(guest (name 76) (sex f) (hobby h3) )
+(guest (name 76) (sex f) (hobby h2) )
+(guest (name 76) (sex f) (hobby h1) )
+(guest (name 77) (sex m) (hobby h1) )
+(guest (name 77) (sex m) (hobby h5) )
+(guest (name 78) (sex m) (hobby h5) )
+(guest (name 78) (sex m) (hobby h1) )
+(guest (name 79) (sex f) (hobby h1) )
+(guest (name 79) (sex f) (hobby h3) )
+(guest (name 79) (sex f) (hobby h4) )
+(guest (name 79) (sex f) (hobby h2) )
+(guest (name 79) (sex f) (hobby h5) )
+(guest (name 80) (sex m) (hobby h5) )
+(guest (name 80) (sex m) (hobby h1) )
+(guest (name 80) (sex m) (hobby h2) )
+(guest (name 80) (sex m) (hobby h4) )
+(guest (name 81) (sex m) (hobby h4) )
+(guest (name 81) (sex m) (hobby h1) )
+(guest (name 82) (sex m) (hobby h3) )
+(guest (name 82) (sex m) (hobby h4) )
+(guest (name 82) (sex m) (hobby h1) )
+(guest (name 82) (sex m) (hobby h2) )
+(guest (name 82) (sex m) (hobby h5) )
+(guest (name 83) (sex f) (hobby h1) )
+(guest (name 83) (sex f) (hobby h3) )
+(guest (name 83) (sex f) (hobby h4) )
+(guest (name 84) (sex m) (hobby h3) )
+(guest (name 84) (sex m) (hobby h4) )
+(guest (name 85) (sex f) (hobby h4) )
+(guest (name 85) (sex f) (hobby h1) )
+(guest (name 86) (sex m) (hobby h3) )
+(guest (name 86) (sex m) (hobby h4) )
+(guest (name 87) (sex m) (hobby h5) )
+(guest (name 87) (sex m) (hobby h4) )
+(guest (name 87) (sex m) (hobby h2) )
+(guest (name 87) (sex m) (hobby h3) )
+(guest (name 88) (sex m) (hobby h2) )
+(guest (name 88) (sex m) (hobby h5) )
+(guest (name 88) (sex m) (hobby h3) )
+(guest (name 88) (sex m) (hobby h1) )
+(guest (name 88) (sex m) (hobby h4) )
+(guest (name 89) (sex f) (hobby h5) )
+(guest (name 89) (sex f) (hobby h2) )
+(guest (name 89) (sex f) (hobby h4) )
+(guest (name 89) (sex f) (hobby h1) )
+(guest (name 90) (sex m) (hobby h2) )
+(guest (name 90) (sex m) (hobby h4) )
+(guest (name 90) (sex m) (hobby h5) )
+(guest (name 91) (sex f) (hobby h2) )
+(guest (name 91) (sex f) (hobby h3) )
+(guest (name 91) (sex f) (hobby h5) )
+(guest (name 91) (sex f) (hobby h1) )
+(guest (name 91) (sex f) (hobby h4) )
+(guest (name 92) (sex f) (hobby h3) )
+(guest (name 92) (sex f) (hobby h1) )
+(guest (name 92) (sex f) (hobby h2) )
+(guest (name 92) (sex f) (hobby h5) )
+(guest (name 93) (sex f) (hobby h3) )
+(guest (name 93) (sex f) (hobby h1) )
+(guest (name 93) (sex f) (hobby h2) )
+(guest (name 94) (sex f) (hobby h2) )
+(guest (name 94) (sex f) (hobby h5) )
+(guest (name 95) (sex f) (hobby h3) )
+(guest (name 95) (sex f) (hobby h4) )
+(guest (name 96) (sex m) (hobby h1) )
+(guest (name 96) (sex m) (hobby h4) )
+(guest (name 96) (sex m) (hobby h2) )
+(guest (name 96) (sex m) (hobby h5) )
+(guest (name 96) (sex m) (hobby h3) )
+(guest (name 97) (sex f) (hobby h4) )
+(guest (name 97) (sex f) (hobby h2) )
+(guest (name 97) (sex f) (hobby h5) )
+(guest (name 98) (sex m) (hobby h5) )
+(guest (name 98) (sex m) (hobby h4) )
+(guest (name 99) (sex f) (hobby h2) )
+(guest (name 99) (sex f) (hobby h5) )
+(guest (name 100) (sex m) (hobby h2) )
+(guest (name 100) (sex m) (hobby h3) )
+(guest (name 100) (sex m) (hobby h5) )
+(guest (name 100) (sex m) (hobby h4) )
+(guest (name 101) (sex f) (hobby h2) )
+(guest (name 101) (sex f) (hobby h1) )
+(guest (name 101) (sex f) (hobby h5) )
+(guest (name 101) (sex f) (hobby h3) )
+(guest (name 101) (sex f) (hobby h4) )
+(guest (name 102) (sex f) (hobby h2) )
+(guest (name 102) (sex f) (hobby h1) )
+(guest (name 102) (sex f) (hobby h5) )
+(guest (name 102) (sex f) (hobby h3) )
+(guest (name 102) (sex f) (hobby h4) )
+(guest (name 103) (sex m) (hobby h2) )
+(guest (name 103) (sex m) (hobby h1) )
+(guest (name 103) (sex m) (hobby h4) )
+(guest (name 103) (sex m) (hobby h3) )
+(guest (name 103) (sex m) (hobby h5) )
+(guest (name 104) (sex m) (hobby h5) )
+(guest (name 104) (sex m) (hobby h3) )
+(guest (name 104) (sex m) (hobby h4) )
+(guest (name 104) (sex m) (hobby h1) )
+(guest (name 104) (sex m) (hobby h2) )
+(guest (name 105) (sex f) (hobby h4) )
+(guest (name 105) (sex f) (hobby h2) )
+(guest (name 106) (sex f) (hobby h4) )
+(guest (name 106) (sex f) (hobby h5) )
+(guest (name 106) (sex f) (hobby h1) )
+(guest (name 107) (sex f) (hobby h3) )
+(guest (name 107) (sex f) (hobby h1) )
+(guest (name 107) (sex f) (hobby h2) )
+(guest (name 107) (sex f) (hobby h5) )
+(guest (name 107) (sex f) (hobby h4) )
+(guest (name 108) (sex f) (hobby h4) )
+(guest (name 108) (sex f) (hobby h5) )
+(guest (name 108) (sex f) (hobby h1) )
+(guest (name 108) (sex f) (hobby h2) )
+(guest (name 108) (sex f) (hobby h3) )
+(guest (name 109) (sex f) (hobby h1) )
+(guest (name 109) (sex f) (hobby h2) )
+(guest (name 110) (sex m) (hobby h5) )
+(guest (name 110) (sex m) (hobby h4) )
+(guest (name 110) (sex m) (hobby h1) )
+(guest (name 110) (sex m) (hobby h2) )
+(guest (name 111) (sex f) (hobby h3) )
+(guest (name 111) (sex f) (hobby h2) )
+(guest (name 112) (sex f) (hobby h4) )
+(guest (name 112) (sex f) (hobby h3) )
+(guest (name 112) (sex f) (hobby h5) )
+(guest (name 112) (sex f) (hobby h2) )
+(guest (name 112) (sex f) (hobby h1) )
+(guest (name 113) (sex f) (hobby h1) )
+(guest (name 113) (sex f) (hobby h3) )
+(guest (name 113) (sex f) (hobby h5) )
+(guest (name 113) (sex f) (hobby h2) )
+(guest (name 114) (sex m) (hobby h3) )
+(guest (name 114) (sex m) (hobby h2) )
+(guest (name 115) (sex m) (hobby h2) )
+(guest (name 115) (sex m) (hobby h1) )
+(guest (name 115) (sex m) (hobby h5) )
+(guest (name 115) (sex m) (hobby h4) )
+(guest (name 116) (sex m) (hobby h3) )
+(guest (name 116) (sex m) (hobby h4) )
+(guest (name 116) (sex m) (hobby h5) )
+(guest (name 116) (sex m) (hobby h1) )
+(guest (name 117) (sex f) (hobby h4) )
+(guest (name 117) (sex f) (hobby h5) )
+(guest (name 117) (sex f) (hobby h2) )
+(guest (name 118) (sex f) (hobby h2) )
+(guest (name 118) (sex f) (hobby h4) )
+(guest (name 118) (sex f) (hobby h3) )
+(guest (name 119) (sex m) (hobby h5) )
+(guest (name 119) (sex m) (hobby h3) )
+(guest (name 120) (sex m) (hobby h5) )
+(guest (name 120) (sex m) (hobby h1) )
+(guest (name 120) (sex m) (hobby h3) )
+(guest (name 120) (sex m) (hobby h2) )
+(guest (name 120) (sex m) (hobby h4) )
+(guest (name 121) (sex f) (hobby h4) )
+(guest (name 121) (sex f) (hobby h2) )
+(guest (name 121) (sex f) (hobby h3) )
+(guest (name 121) (sex f) (hobby h5) )
+(guest (name 122) (sex m) (hobby h1) )
+(guest (name 122) (sex m) (hobby h2) )
+(guest (name 122) (sex m) (hobby h5) )
+(guest (name 123) (sex m) (hobby h2) )
+(guest (name 123) (sex m) (hobby h3) )
+(guest (name 123) (sex m) (hobby h1) )
+(guest (name 123) (sex m) (hobby h5) )
+(guest (name 124) (sex f) (hobby h2) )
+(guest (name 124) (sex f) (hobby h3) )
+(guest (name 124) (sex f) (hobby h4) )
+(guest (name 125) (sex f) (hobby h3) )
+(guest (name 125) (sex f) (hobby h5) )
+(guest (name 125) (sex f) (hobby h2) )
+(guest (name 125) (sex f) (hobby h4) )
+(guest (name 126) (sex f) (hobby h2) )
+(guest (name 126) (sex f) (hobby h3) )
+(guest (name 126) (sex f) (hobby h1) )
+(guest (name 126) (sex f) (hobby h4) )
+(guest (name 127) (sex f) (hobby h5) )
+(guest (name 127) (sex f) (hobby h1) )
+(guest (name 128) (sex f) (hobby h2) )
+(guest (name 128) (sex f) (hobby h4) )
+(guest (name 128) (sex f) (hobby h1) )
+(guest (name 128) (sex f) (hobby h3) )
+(last_seat (seat 128) )
+(context (state start) )

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners16.dat
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners16.dat	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners16.dat	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,42 @@
+(guest (name n1) (sex f) (hobby h3))
+(guest (name n1) (sex f) (hobby h1))
+(guest (name n1) (sex f) (hobby h2))
+(guest (name n2) (sex f) (hobby h3))
+(guest (name n2) (sex f) (hobby h2))
+(guest (name n3) (sex m) (hobby h1))
+(guest (name n3) (sex m) (hobby h3))
+(guest (name n4) (sex m) (hobby h2))
+(guest (name n4) (sex m) (hobby h1))
+(guest (name n5) (sex m) (hobby h2))
+(guest (name n5) (sex m) (hobby h3))
+(guest (name n6) (sex m) (hobby h2))
+(guest (name n6) (sex m) (hobby h1))
+(guest (name n7) (sex f) (hobby h2))
+(guest (name n7) (sex f) (hobby h1))
+(guest (name n7) (sex f) (hobby h3))
+(guest (name n8) (sex f) (hobby h3))
+(guest (name n8) (sex f) (hobby h2))
+(guest (name n9) (sex f) (hobby h1))
+(guest (name n9) (sex f) (hobby h3))
+(guest (name n9) (sex f) (hobby h2))
+(guest (name n10) (sex m) (hobby h2))
+(guest (name n10) (sex m) (hobby h3))
+(guest (name n11) (sex m) (hobby h3))
+(guest (name n11) (sex m) (hobby h2))
+(guest (name n11) (sex m) (hobby h1))
+(guest (name n12) (sex m) (hobby h3))
+(guest (name n12) (sex m) (hobby h1))
+(guest (name n13) (sex m) (hobby h2))
+(guest (name n13) (sex m) (hobby h3))
+(guest (name n13) (sex m) (hobby h1))
+(guest (name n14) (sex f) (hobby h3))
+(guest (name n14) (sex f) (hobby h1))
+(guest (name n15) (sex f) (hobby h3))
+(guest (name n15) (sex f) (hobby h1))
+(guest (name n15) (sex f) (hobby h2))
+(guest (name n16) (sex f) (hobby h3))
+(guest (name n16) (sex f) (hobby h2))
+(guest (name n16) (sex f) (hobby h1))
+(last_seat (seat 16))
+
+(context (state start))

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners32.dat
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners32.dat	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners32.dat	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,84 @@
+(guest (name n1) (sex m) (hobby h1))
+(guest (name n1) (sex m) (hobby h3))
+(guest (name n2) (sex f) (hobby h3))
+(guest (name n2) (sex f) (hobby h2))
+(guest (name n2) (sex f) (hobby h1))
+(guest (name n3) (sex f) (hobby h1))
+(guest (name n3) (sex f) (hobby h2))
+(guest (name n4) (sex f) (hobby h3))
+(guest (name n4) (sex f) (hobby h1))
+(guest (name n5) (sex f) (hobby h1))
+(guest (name n5) (sex f) (hobby h2))
+(guest (name n6) (sex m) (hobby h1))
+(guest (name n6) (sex m) (hobby h2))
+(guest (name n6) (sex m) (hobby h3))
+(guest (name n7) (sex f) (hobby h2))
+(guest (name n7) (sex f) (hobby h1))
+(guest (name n7) (sex f) (hobby h3))
+(guest (name n8) (sex f) (hobby h1))
+(guest (name n8) (sex f) (hobby h3))
+(guest (name n8) (sex f) (hobby h2))
+(guest (name n9) (sex f) (hobby h1))
+(guest (name n9) (sex f) (hobby h3))
+(guest (name n9) (sex f) (hobby h2))
+(guest (name n10) (sex m) (hobby h2))
+(guest (name n10) (sex m) (hobby h1))
+(guest (name n11) (sex m) (hobby h2))
+(guest (name n11) (sex m) (hobby h1))
+(guest (name n12) (sex m) (hobby h3))
+(guest (name n12) (sex m) (hobby h2))
+(guest (name n13) (sex m) (hobby h1))
+(guest (name n13) (sex m) (hobby h3))
+(guest (name n14) (sex m) (hobby h3))
+(guest (name n14) (sex m) (hobby h2))
+(guest (name n15) (sex f) (hobby h2))
+(guest (name n15) (sex f) (hobby h1))
+(guest (name n15) (sex f) (hobby h3))
+(guest (name n16) (sex f) (hobby h3))
+(guest (name n16) (sex f) (hobby h2))
+(guest (name n16) (sex f) (hobby h1))
+(guest (name n17) (sex m) (hobby h3))
+(guest (name n17) (sex m) (hobby h2))
+(guest (name n18) (sex f) (hobby h2))
+(guest (name n18) (sex f) (hobby h1))
+(guest (name n19) (sex f) (hobby h1))
+(guest (name n19) (sex f) (hobby h2))
+(guest (name n19) (sex f) (hobby h3))
+(guest (name n20) (sex f) (hobby h1))
+(guest (name n20) (sex f) (hobby h2))
+(guest (name n20) (sex f) (hobby h3))
+(guest (name n21) (sex m) (hobby h2))
+(guest (name n21) (sex m) (hobby h3))
+(guest (name n21) (sex m) (hobby h1))
+(guest (name n22) (sex f) (hobby h1))
+(guest (name n22) (sex f) (hobby h2))
+(guest (name n22) (sex f) (hobby h3))
+(guest (name n23) (sex f) (hobby h3))
+(guest (name n23) (sex f) (hobby h1))
+(guest (name n23) (sex f) (hobby h2))
+(guest (name n24) (sex m) (hobby h1))
+(guest (name n24) (sex m) (hobby h3))
+(guest (name n25) (sex f) (hobby h3))
+(guest (name n25) (sex f) (hobby h2))
+(guest (name n25) (sex f) (hobby h1))
+(guest (name n26) (sex f) (hobby h3))
+(guest (name n26) (sex f) (hobby h2))
+(guest (name n26) (sex f) (hobby h1))
+(guest (name n27) (sex m) (hobby h3))
+(guest (name n27) (sex m) (hobby h1))
+(guest (name n27) (sex m) (hobby h2))
+(guest (name n28) (sex m) (hobby h3))
+(guest (name n28) (sex m) (hobby h1))
+(guest (name n29) (sex m) (hobby h3))
+(guest (name n29) (sex m) (hobby h2))
+(guest (name n29) (sex m) (hobby h1))
+(guest (name n30) (sex m) (hobby h2))
+(guest (name n30) (sex m) (hobby h1))
+(guest (name n30) (sex m) (hobby h3))
+(guest (name n31) (sex m) (hobby h2))
+(guest (name n31) (sex m) (hobby h1))
+(guest (name n32) (sex m) (hobby h1))
+(guest (name n32) (sex m) (hobby h3))
+(guest (name n32) (sex m) (hobby h2))
+(last_seat (seat 32))
+(context (state start))

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners5.dat
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners5.dat	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners5.dat	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,11 @@
+(guest (name n1) (sex m) (hobby  h1)  )
+(guest (name n2) (sex f) (hobby  h1)  )
+(guest (name n2) (sex f) (hobby  h3)  )
+(guest (name n3) (sex m) (hobby  h3)  )
+(guest (name n3) (sex m) (hobby  h1)  )
+(guest (name n4) (sex f) (hobby  h1)  )
+(guest (name n4) (sex f) (hobby  h3)  )
+(guest (name n5) (sex f) (hobby  h2)  )
+(guest (name n5) (sex f) (hobby  h1)  )
+(last_seat (seat 5)  )
+(context (state start))
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners64.dat
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners64.dat	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners64.dat	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,169 @@
+(guest (name 1) (sex m) (hobby h2) )
+(guest (name 1) (sex m) (hobby h1) )
+(guest (name 1) (sex m) (hobby h3) )
+(guest (name 2) (sex f) (hobby h2) )
+(guest (name 2) (sex f) (hobby h1) )
+(guest (name 2) (sex f) (hobby h3) )
+(guest (name 3) (sex m) (hobby h3) )
+(guest (name 3) (sex m) (hobby h2) )
+(guest (name 4) (sex m) (hobby h3) )
+(guest (name 4) (sex m) (hobby h2) )
+(guest (name 4) (sex m) (hobby h1) )
+(guest (name 5) (sex m) (hobby h2) )
+(guest (name 5) (sex m) (hobby h1) )
+(guest (name 5) (sex m) (hobby h3) )
+(guest (name 6) (sex m) (hobby h2) )
+(guest (name 6) (sex m) (hobby h3) )
+(guest (name 6) (sex m) (hobby h1) )
+(guest (name 7) (sex f) (hobby h1) )
+(guest (name 7) (sex f) (hobby h2) )
+(guest (name 7) (sex f) (hobby h3) )
+(guest (name 8) (sex m) (hobby h3) )
+(guest (name 8) (sex m) (hobby h1) )
+(guest (name 9) (sex m) (hobby h2) )
+(guest (name 9) (sex m) (hobby h3) )
+(guest (name 9) (sex m) (hobby h1) )
+(guest (name 10) (sex m) (hobby h3) )
+(guest (name 10) (sex m) (hobby h2) )
+(guest (name 10) (sex m) (hobby h1) )
+(guest (name 11) (sex m) (hobby h1) )
+(guest (name 11) (sex m) (hobby h3) )
+(guest (name 11) (sex m) (hobby h2) )
+(guest (name 12) (sex f) (hobby h3) )
+(guest (name 12) (sex f) (hobby h1) )
+(guest (name 12) (sex f) (hobby h2) )
+(guest (name 13) (sex m) (hobby h2) )
+(guest (name 13) (sex m) (hobby h3) )
+(guest (name 14) (sex m) (hobby h1) )
+(guest (name 14) (sex m) (hobby h2) )
+(guest (name 15) (sex m) (hobby h2) )
+(guest (name 15) (sex m) (hobby h3) )
+(guest (name 15) (sex m) (hobby h1) )
+(guest (name 16) (sex f) (hobby h2) )
+(guest (name 16) (sex f) (hobby h3) )
+(guest (name 17) (sex f) (hobby h3) )
+(guest (name 17) (sex f) (hobby h2) )
+(guest (name 18) (sex m) (hobby h1) )
+(guest (name 18) (sex m) (hobby h3) )
+(guest (name 18) (sex m) (hobby h2) )
+(guest (name 19) (sex f) (hobby h3) )
+(guest (name 19) (sex f) (hobby h1) )
+(guest (name 20) (sex f) (hobby h1) )
+(guest (name 20) (sex f) (hobby h3) )
+(guest (name 20) (sex f) (hobby h2) )
+(guest (name 21) (sex m) (hobby h2) )
+(guest (name 21) (sex m) (hobby h3) )
+(guest (name 22) (sex m) (hobby h2) )
+(guest (name 22) (sex m) (hobby h3) )
+(guest (name 23) (sex f) (hobby h1) )
+(guest (name 23) (sex f) (hobby h2) )
+(guest (name 24) (sex f) (hobby h3) )
+(guest (name 24) (sex f) (hobby h1) )
+(guest (name 24) (sex f) (hobby h2) )
+(guest (name 25) (sex f) (hobby h3) )
+(guest (name 25) (sex f) (hobby h1) )
+(guest (name 25) (sex f) (hobby h2) )
+(guest (name 26) (sex m) (hobby h2) )
+(guest (name 26) (sex m) (hobby h1) )
+(guest (name 26) (sex m) (hobby h3) )
+(guest (name 27) (sex f) (hobby h2) )
+(guest (name 27) (sex f) (hobby h3) )
+(guest (name 27) (sex f) (hobby h1) )
+(guest (name 28) (sex m) (hobby h1) )
+(guest (name 28) (sex m) (hobby h2) )
+(guest (name 29) (sex f) (hobby h2) )
+(guest (name 29) (sex f) (hobby h3) )
+(guest (name 29) (sex f) (hobby h1) )
+(guest (name 30) (sex f) (hobby h2) )
+(guest (name 30) (sex f) (hobby h1) )
+(guest (name 30) (sex f) (hobby h3) )
+(guest (name 31) (sex m) (hobby h1) )
+(guest (name 31) (sex m) (hobby h2) )
+(guest (name 31) (sex m) (hobby h3) )
+(guest (name 32) (sex m) (hobby h1) )
+(guest (name 32) (sex m) (hobby h2) )
+(guest (name 33) (sex m) (hobby h2) )
+(guest (name 33) (sex m) (hobby h3) )
+(guest (name 33) (sex m) (hobby h1) )
+(guest (name 34) (sex f) (hobby h2) )
+(guest (name 34) (sex f) (hobby h1) )
+(guest (name 34) (sex f) (hobby h3) )
+(guest (name 35) (sex f) (hobby h2) )
+(guest (name 35) (sex f) (hobby h3) )
+(guest (name 36) (sex m) (hobby h2) )
+(guest (name 36) (sex m) (hobby h1) )
+(guest (name 37) (sex m) (hobby h2) )
+(guest (name 37) (sex m) (hobby h1) )
+(guest (name 38) (sex f) (hobby h1) )
+(guest (name 38) (sex f) (hobby h3) )
+(guest (name 38) (sex f) (hobby h2) )
+(guest (name 39) (sex m) (hobby h3) )
+(guest (name 39) (sex m) (hobby h1) )
+(guest (name 39) (sex m) (hobby h2) )
+(guest (name 40) (sex f) (hobby h1) )
+(guest (name 40) (sex f) (hobby h2) )
+(guest (name 40) (sex f) (hobby h3) )
+(guest (name 41) (sex m) (hobby h2) )
+(guest (name 41) (sex m) (hobby h1) )
+(guest (name 41) (sex m) (hobby h3) )
+(guest (name 42) (sex m) (hobby h3) )
+(guest (name 42) (sex m) (hobby h1) )
+(guest (name 43) (sex m) (hobby h1) )
+(guest (name 43) (sex m) (hobby h3) )
+(guest (name 43) (sex m) (hobby h2) )
+(guest (name 44) (sex m) (hobby h3) )
+(guest (name 44) (sex m) (hobby h1) )
+(guest (name 44) (sex m) (hobby h2) )
+(guest (name 45) (sex m) (hobby h1) )
+(guest (name 45) (sex m) (hobby h2) )
+(guest (name 46) (sex f) (hobby h1) )
+(guest (name 46) (sex f) (hobby h2) )
+(guest (name 46) (sex f) (hobby h3) )
+(guest (name 47) (sex m) (hobby h1) )
+(guest (name 47) (sex m) (hobby h2) )
+(guest (name 48) (sex f) (hobby h3) )
+(guest (name 48) (sex f) (hobby h2) )
+(guest (name 49) (sex m) (hobby h3) )
+(guest (name 49) (sex m) (hobby h2) )
+(guest (name 50) (sex m) (hobby h2) )
+(guest (name 50) (sex m) (hobby h3) )
+(guest (name 51) (sex f) (hobby h2) )
+(guest (name 51) (sex f) (hobby h1) )
+(guest (name 51) (sex f) (hobby h3) )
+(guest (name 52) (sex m) (hobby h1) )
+(guest (name 52) (sex m) (hobby h2) )
+(guest (name 52) (sex m) (hobby h3) )
+(guest (name 53) (sex f) (hobby h2) )
+(guest (name 53) (sex f) (hobby h1) )
+(guest (name 54) (sex f) (hobby h1) )
+(guest (name 54) (sex f) (hobby h2) )
+(guest (name 54) (sex f) (hobby h3) )
+(guest (name 55) (sex f) (hobby h1) )
+(guest (name 55) (sex f) (hobby h2) )
+(guest (name 55) (sex f) (hobby h3) )
+(guest (name 56) (sex f) (hobby h2) )
+(guest (name 56) (sex f) (hobby h1) )
+(guest (name 56) (sex f) (hobby h3) )
+(guest (name 57) (sex f) (hobby h3) )
+(guest (name 57) (sex f) (hobby h2) )
+(guest (name 57) (sex f) (hobby h1) )
+(guest (name 58) (sex f) (hobby h3) )
+(guest (name 58) (sex f) (hobby h1) )
+(guest (name 58) (sex f) (hobby h2) )
+(guest (name 59) (sex f) (hobby h1) )
+(guest (name 59) (sex f) (hobby h2) )
+(guest (name 59) (sex f) (hobby h3) )
+(guest (name 60) (sex f) (hobby h3) )
+(guest (name 60) (sex f) (hobby h1) )
+(guest (name 61) (sex f) (hobby h3) )
+(guest (name 61) (sex f) (hobby h2) )
+(guest (name 62) (sex f) (hobby h1) )
+(guest (name 62) (sex f) (hobby h2) )
+(guest (name 62) (sex f) (hobby h3) )
+(guest (name 63) (sex f) (hobby h3) )
+(guest (name 63) (sex f) (hobby h1) )
+(guest (name 63) (sex f) (hobby h2) )
+(guest (name 64) (sex f) (hobby h3) )
+(guest (name 64) (sex f) (hobby h2) )  
+(last_seat (seat 64) )
+(context (state start))
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners8.dat
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners8.dat	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/manners8.dat	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,21 @@
+(guest (name n1) (sex m) (hobby h3) )
+(guest (name n1) (sex m) (hobby h2) )
+(guest (name n2) (sex m) (hobby h2) )
+(guest (name n2) (sex m) (hobby h3) )
+(guest (name n3) (sex m) (hobby h1) )
+(guest (name n3) (sex m) (hobby h2) )
+(guest (name n3) (sex m) (hobby h3) )
+(guest (name n4) (sex f) (hobby h3) )
+(guest (name n4) (sex f) (hobby h2) )
+(guest (name n5) (sex f) (hobby h1) )
+(guest (name n5) (sex f) (hobby h2) )
+(guest (name n5) (sex f) (hobby h3) )
+(guest (name n6) (sex f) (hobby h3) )
+(guest (name n6) (sex f) (hobby h1) )
+(guest (name n6) (sex f) (hobby h2) )
+(guest (name n7) (sex f) (hobby h3) )
+(guest (name n7) (sex f) (hobby h2) )
+(guest (name n8) (sex m) (hobby h3) )
+(guest (name n8) (sex m) (hobby h1) )
+(last_seat (seat 8) )
+(context (state start))  
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/rule-agent-config.properties
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/rule-agent-config.properties	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/rule-agent-config.properties	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,33 @@
+##
+## RuleAgent configuration file example
+##
+
+#setting this means the rulebase will be created fresh whenever there are 
+#changes
+newInstance=true
+
+#this points to a binary compiled rule package, you can have spaces
+#seperating multiple files
+file=/foo/bar/boo.pkg /foo/bar/boo2.pkg
+
+#this specifies that packages may appear in a directory
+#it will pick up whatever files are dumped in there (.pkg files like above)
+dir=/my/dir
+
+#this specifies a list of urls for packages - these urls 
+#are those that are exposed by the BRMS
+url=http://some.url/here http://some.url/here
+
+#the following can be used with the urls to keep a local cache
+#so if the runtime server is restarted, the BRMS does not need
+#to be available
+localCacheDir=/foo/bar/cache
+
+#this specifies the frequency at which the sources will be checked for
+#changes (in seconds). If you don't set this, it will mean that you have
+#to manually poll
+poll=30
+
+
+#this specifies the name of this config, necessary in case logging is used.
+name=MyConfig
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/sample-agent-config.properties
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/sample-agent-config.properties	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/sample-agent-config.properties	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,6 @@
+newInstance=true
+dir=/home/packages
+file=/foo/bar.pkg \
+	 /wee/waa.pkg \
+	 /wee/waa2.pkg
+poll=10
\ No newline at end of file

Added: labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/waltz12.dat
===================================================================
--- labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/waltz12.dat	                        (rev 0)
+++ labs/jbossrules/branches/temporal_rete/drools-core-window-ITA/src/test/resources/waltz12.dat	2008-04-21 10:35:38 UTC (rev 19665)
@@ -0,0 +1,985 @@
+(stage (value duplicate))
+(line (p1 50003) (p2 60003))
+(line (p1 30005) (p2 30006))
+(line (p1 80005) (p2 80006))
+(line (p1 50008) (p2 60008))
+(line (p1 0) (p2 20000))
+(line (p1 20000) (p2 30000))
+(line (p1 30000) (p2 40000))
+(line (p1 0) (p2 2))
+(line (p1 2) (p2 3))
+(line (p1 3) (p2 4))
+(line (p1 4) (p2 40004))
+(line (p1 40004) (p2 40000))
+(line (p1 40000) (p2 50001))
+(line (p1 50001) (p2 50002))
+(line (p1 50002) (p2 50003))
+(line (p1 50003) (p2 50005))
+(line (p1 50005) (p2 40004))
+(line (p1 50005) (p2 30005))
+(line (p1 30005) (p2 20005))
+(line (p1 20005) (p2 10005))
+(line (p1 10005) (p2 4))
+(line (p1 60000) (p2 80000))
+(line (p1 80000) (p2 90000))
+(line (p1 90000) (p2 100000))
+(line (p1 60000) (p2 60002))
+(line (p1 60002) (p2 60003))
+(line (p1 60003) (p2 60004))
+(line (p1 60004) (p2 100004))
+(line (p1 100004) (p2 100000))
+(line (p1 100000) (p2 110001))
+(line (p1 110001) (p2 110002))
+(line (p1 110002) (p2 110003))
+(line (p1 110003) (p2 110005))
+(line (p1 110005) (p2 100004))
+(line (p1 110005) (p2 90005))
+(line (p1 90005) (p2 80005))
+(line (p1 80005) (p2 70005))
+(line (p1 70005) (p2 60004))
+(line (p1 6) (p2 20006))
+(line (p1 20006) (p2 30006))
+(line (p1 30006) (p2 40006))
+(line (p1 6) (p2 8))
+(line (p1 8) (p2 9))
+(line (p1 9) (p2 10))
+(line (p1 10) (p2 40010))
+(line (p1 40010) (p2 40006))
+(line (p1 40006) (p2 50007))
+(line (p1 50007) (p2 50008))
+(line (p1 50008) (p2 50009))
+(line (p1 50009) (p2 50011))
+(line (p1 50011) (p2 40010))
+(line (p1 50011) (p2 30011))
+(line (p1 30011) (p2 20011))
+(line (p1 20011) (p2 10011))
+(line (p1 10011) (p2 10))
+(line (p1 60006) (p2 80006))
+(line (p1 80006) (p2 90006))
+(line (p1 90006) (p2 100006))
+(line (p1 60006) (p2 60008))
+(line (p1 60008) (p2 60009))
+(line (p1 60009) (p2 60010))
+(line (p1 60010) (p2 100010))
+(line (p1 100010) (p2 100006))
+(line (p1 100006) (p2 110007))
+(line (p1 110007) (p2 110008))
+(line (p1 110008) (p2 110009))
+(line (p1 110009) (p2 110011))
+(line (p1 110011) (p2 100010))
+(line (p1 110011) (p2 90011))
+(line (p1 90011) (p2 80011))
+(line (p1 80011) (p2 70011))
+(line (p1 70011) (p2 60010))
+(line (p1 170003) (p2 180003))
+(line (p1 150005) (p2 150006))
+(line (p1 200005) (p2 200006))
+(line (p1 170008) (p2 180008))
+(line (p1 120000) (p2 140000))
+(line (p1 140000) (p2 150000))
+(line (p1 150000) (p2 160000))
+(line (p1 120000) (p2 120002))
+(line (p1 120002) (p2 120003))
+(line (p1 120003) (p2 120004))
+(line (p1 120004) (p2 160004))
+(line (p1 160004) (p2 160000))
+(line (p1 160000) (p2 170001))
+(line (p1 170001) (p2 170002))
+(line (p1 170002) (p2 170003))
+(line (p1 170003) (p2 170005))
+(line (p1 170005) (p2 160004))
+(line (p1 170005) (p2 150005))
+(line (p1 150005) (p2 140005))
+(line (p1 140005) (p2 130005))
+(line (p1 130005) (p2 120004))
+(line (p1 180000) (p2 200000))
+(line (p1 200000) (p2 210000))
+(line (p1 210000) (p2 220000))
+(line (p1 180000) (p2 180002))
+(line (p1 180002) (p2 180003))
+(line (p1 180003) (p2 180004))
+(line (p1 180004) (p2 220004))
+(line (p1 220004) (p2 220000))
+(line (p1 220000) (p2 230001))
+(line (p1 230001) (p2 230002))
+(line (p1 230002) (p2 230003))
+(line (p1 230003) (p2 230005))
+(line (p1 230005) (p2 220004))
+(line (p1 230005) (p2 210005))
+(line (p1 210005) (p2 200005))
+(line (p1 200005) (p2 190005))
+(line (p1 190005) (p2 180004))
+(line (p1 120006) (p2 140006))
+(line (p1 140006) (p2 150006))
+(line (p1 150006) (p2 160006))
+(line (p1 120006) (p2 120008))
+(line (p1 120008) (p2 120009))
+(line (p1 120009) (p2 120010))
+(line (p1 120010) (p2 160010))
+(line (p1 160010) (p2 160006))
+(line (p1 160006) (p2 170007))
+(line (p1 170007) (p2 170008))
+(line (p1 170008) (p2 170009))
+(line (p1 170009) (p2 170011))
+(line (p1 170011) (p2 160010))
+(line (p1 170011) (p2 150011))
+(line (p1 150011) (p2 140011))
+(line (p1 140011) (p2 130011))
+(line (p1 130011) (p2 120010))
+(line (p1 180006) (p2 200006))
+(line (p1 200006) (p2 210006))
+(line (p1 210006) (p2 220006))
+(line (p1 180006) (p2 180008))
+(line (p1 180008) (p2 180009))
+(line (p1 180009) (p2 180010))
+(line (p1 180010) (p2 220010))
+(line (p1 220010) (p2 220006))
+(line (p1 220006) (p2 230007))
+(line (p1 230007) (p2 230008))
+(line (p1 230008) (p2 230009))
+(line (p1 230009) (p2 230011))
+(line (p1 230011) (p2 220010))
+(line (p1 230011) (p2 210011))
+(line (p1 210011) (p2 200011))
+(line (p1 200011) (p2 190011))
+(line (p1 190011) (p2 180010))
+(line (p1 110003) (p2 120003))
+(line (p1 90005) (p2 90006))
+(line (p1 140005) (p2 140006))
+(line (p1 110008) (p2 120008))
+(line (p1 290003) (p2 300003))
+(line (p1 270005) (p2 270006))
+(line (p1 320005) (p2 320006))
+(line (p1 290008) (p2 300008))
+(line (p1 240000) (p2 260000))
+(line (p1 260000) (p2 270000))
+(line (p1 270000) (p2 280000))
+(line (p1 240000) (p2 240002))
+(line (p1 240002) (p2 240003))
+(line (p1 240003) (p2 240004))
+(line (p1 240004) (p2 280004))
+(line (p1 280004) (p2 280000))
+(line (p1 280000) (p2 290001))
+(line (p1 290001) (p2 290002))
+(line (p1 290002) (p2 290003))
+(line (p1 290003) (p2 290005))
+(line (p1 290005) (p2 280004))
+(line (p1 290005) (p2 270005))
+(line (p1 270005) (p2 260005))
+(line (p1 260005) (p2 250005))
+(line (p1 250005) (p2 240004))
+(line (p1 300000) (p2 320000))
+(line (p1 320000) (p2 330000))
+(line (p1 330000) (p2 340000))
+(line (p1 300000) (p2 300002))
+(line (p1 300002) (p2 300003))
+(line (p1 300003) (p2 300004))
+(line (p1 300004) (p2 340004))
+(line (p1 340004) (p2 340000))
+(line (p1 340000) (p2 350001))
+(line (p1 350001) (p2 350002))
+(line (p1 350002) (p2 350003))
+(line (p1 350003) (p2 350005))
+(line (p1 350005) (p2 340004))
+(line (p1 350005) (p2 330005))
+(line (p1 330005) (p2 320005))
+(line (p1 320005) (p2 310005))
+(line (p1 310005) (p2 300004))
+(line (p1 240006) (p2 260006))
+(line (p1 260006) (p2 270006))
+(line (p1 270006) (p2 280006))
+(line (p1 240006) (p2 240008))
+(line (p1 240008) (p2 240009))
+(line (p1 240009) (p2 240010))
+(line (p1 240010) (p2 280010))
+(line (p1 280010) (p2 280006))
+(line (p1 280006) (p2 290007))
+(line (p1 290007) (p2 290008))
+(line (p1 290008) (p2 290009))
+(line (p1 290009) (p2 290011))
+(line (p1 290011) (p2 280010))
+(line (p1 290011) (p2 270011))
+(line (p1 270011) (p2 260011))
+(line (p1 260011) (p2 250011))
+(line (p1 250011) (p2 240010))
+(line (p1 300006) (p2 320006))
+(line (p1 320006) (p2 330006))
+(line (p1 330006) (p2 340006))
+(line (p1 300006) (p2 300008))
+(line (p1 300008) (p2 300009))
+(line (p1 300009) (p2 300010))
+(line (p1 300010) (p2 340010))
+(line (p1 340010) (p2 340006))
+(line (p1 340006) (p2 350007))
+(line (p1 350007) (p2 350008))
+(line (p1 350008) (p2 350009))
+(line (p1 350009) (p2 350011))
+(line (p1 350011) (p2 340010))
+(line (p1 350011) (p2 330011))
+(line (p1 330011) (p2 320011))
+(line (p1 320011) (p2 310011))
+(line (p1 310011) (p2 300010))
+(line (p1 230003) (p2 240003))
+(line (p1 210005) (p2 210006))
+(line (p1 260005) (p2 260006))
+(line (p1 230008) (p2 240008))
+(line (p1 410003) (p2 420003))
+(line (p1 390005) (p2 390006))
+(line (p1 440005) (p2 440006))
+(line (p1 410008) (p2 420008))
+(line (p1 360000) (p2 380000))
+(line (p1 380000) (p2 390000))
+(line (p1 390000) (p2 400000))
+(line (p1 360000) (p2 360002))
+(line (p1 360002) (p2 360003))
+(line (p1 360003) (p2 360004))
+(line (p1 360004) (p2 400004))
+(line (p1 400004) (p2 400000))
+(line (p1 400000) (p2 410001))
+(line (p1 410001) (p2 410002))
+(line (p1 410002) (p2 410003))
+(line (p1 410003) (p2 410005))
+(line (p1 410005) (p2 400004))
+(line (p1 410005) (p2 390005))
+(line (p1 390005) (p2 380005))
+(line (p1 380005) (p2 370005))
+(line (p1 370005) (p2 360004))
+(line (p1 420000) (p2 440000))
+(line (p1 440000) (p2 450000))
+(line (p1 450000) (p2 460000))
+(line (p1 420000) (p2 420002))
+(line (p1 420002) (p2 420003))
+(line (p1 420003) (p2 420004))
+(line (p1 420004) (p2 460004))
+(line (p1 460004) (p2 460000))
+(line (p1 460000) (p2 470001))
+(line (p1 470001) (p2 470002))
+(line (p1 470002) (p2 470003))
+(line (p1 470003) (p2 470005))
+(line (p1 470005) (p2 460004))
+(line (p1 470005) (p2 450005))
+(line (p1 450005) (p2 440005))
+(line (p1 440005) (p2 430005))
+(line (p1 430005) (p2 420004))
+(line (p1 360006) (p2 380006))
+(line (p1 380006) (p2 390006))
+(line (p1 390006) (p2 400006))
+(line (p1 360006) (p2 360008))
+(line (p1 360008) (p2 360009))
+(line (p1 360009) (p2 360010))
+(line (p1 360010) (p2 400010))
+(line (p1 400010) (p2 400006))
+(line (p1 400006) (p2 410007))
+(line (p1 410007) (p2 410008))
+(line (p1 410008) (p2 410009))
+(line (p1 410009) (p2 410011))
+(line (p1 410011) (p2 400010))
+(line (p1 410011) (p2 390011))
+(line (p1 390011) (p2 380011))
+(line (p1 380011) (p2 370011))
+(line (p1 370011) (p2 360010))
+(line (p1 420006) (p2 440006))
+(line (p1 440006) (p2 450006))
+(line (p1 450006) (p2 460006))
+(line (p1 420006) (p2 420008))
+(line (p1 420008) (p2 420009))
+(line (p1 420009) (p2 420010))
+(line (p1 420010) (p2 460010))
+(line (p1 460010) (p2 460006))
+(line (p1 460006) (p2 470007))
+(line (p1 470007) (p2 470008))
+(line (p1 470008) (p2 470009))
+(line (p1 470009) (p2 470011))
+(line (p1 470011) (p2 460010))
+(line (p1 470011) (p2 450011))
+(line (p1 450011) (p2 440011))
+(line (p1 440011) (p2 430011))
+(line (p1 430011) (p2 420010))
+(line (p1 350003) (p2 360003))
+(line (p1 330005) (p2 330006))
+(line (p1 380005) (p2 380006))
+(line (p1 350008) (p2 360008))
+(line (p1 530003) (p2 540003))
+(line (p1 510005) (p2 510006))
+(line (p1 560005) (p2 560006))
+(line (p1 530008) (p2 540008))
+(line (p1 480000) (p2 500000))
+(line (p1 500000) (p2 510000))
+(line (p1 510000) (p2 520000))
+(line (p1 480000) (p2 480002))
+(line (p1 480002) (p2 480003))
+(line (p1 480003) (p2 480004))
+(line (p1 480004) (p2 520004))
+(line (p1 520004) (p2 520000))
+(line (p1 520000) (p2 530001))
+(line (p1 530001) (p2 530002))
+(line (p1 530002) (p2 530003))
+(line (p1 530003) (p2 530005))
+(line (p1 530005) (p2 520004))
+(line (p1 530005) (p2 510005))
+(line (p1 510005) (p2 500005))
+(line (p1 500005) (p2 490005))
+(line (p1 490005) (p2 480004))
+(line (p1 540000) (p2 560000))
+(line (p1 560000) (p2 570000))
+(line (p1 570000) (p2 580000))
+(line (p1 540000) (p2 540002))
+(line (p1 540002) (p2 540003))
+(line (p1 540003) (p2 540004))
+(line (p1 540004) (p2 580004))
+(line (p1 580004) (p2 580000))
+(line (p1 580000) (p2 590001))
+(line (p1 590001) (p2 590002))
+(line (p1 590002) (p2 590003))
+(line (p1 590003) (p2 590005))
+(line (p1 590005) (p2 580004))
+(line (p1 590005) (p2 570005))
+(line (p1 570005) (p2 560005))
+(line (p1 560005) (p2 550005))
+(line (p1 550005) (p2 540004))
+(line (p1 480006) (p2 500006))
+(line (p1 500006) (p2 510006))
+(line (p1 510006) (p2 520006))
+(line (p1 480006) (p2 480008))
+(line (p1 480008) (p2 480009))
+(line (p1 480009) (p2 480010))
+(line (p1 480010) (p2 520010))
+(line (p1 520010) (p2 520006))
+(line (p1 520006) (p2 530007))
+(line (p1 530007) (p2 530008))
+(line (p1 530008) (p2 530009))
+(line (p1 530009) (p2 530011))
+(line (p1 530011) (p2 520010))
+(line (p1 530011) (p2 510011))
+(line (p1 510011) (p2 500011))
+(line (p1 500011) (p2 490011))
+(line (p1 490011) (p2 480010))
+(line (p1 540006) (p2 560006))
+(line (p1 560006) (p2 570006))
+(line (p1 570006) (p2 580006))
+(line (p1 540006) (p2 540008))
+(line (p1 540008) (p2 540009))
+(line (p1 540009) (p2 540010))
+(line (p1 540010) (p2 580010))
+(line (p1 580010) (p2 580006))
+(line (p1 580006) (p2 590007))
+(line (p1 590007) (p2 590008))
+(line (p1 590008) (p2 590009))
+(line (p1 590009) (p2 590011))
+(line (p1 590011) (p2 580010))
+(line (p1 590011) (p2 570011))
+(line (p1 570011) (p2 560011))
+(line (p1 560011) (p2 550011))
+(line (p1 550011) (p2 540010))
+(line (p1 470003) (p2 480003))
+(line (p1 450005) (p2 450006))
+(line (p1 500005) (p2 500006))
+(line (p1 470008) (p2 480008))
+(line (p1 650003) (p2 660003))
+(line (p1 630005) (p2 630006))
+(line (p1 680005) (p2 680006))
+(line (p1 650008) (p2 660008))
+(line (p1 600000) (p2 620000))
+(line (p1 620000) (p2 630000))
+(line (p1 630000) (p2 640000))
+(line (p1 600000) (p2 600002))
+(line (p1 600002) (p2 600003))
+(line (p1 600003) (p2 600004))
+(line (p1 600004) (p2 640004))
+(line (p1 640004) (p2 640000))
+(line (p1 640000) (p2 650001))
+(line (p1 650001) (p2 650002))
+(line (p1 650002) (p2 650003))
+(line (p1 650003) (p2 650005))
+(line (p1 650005) (p2 640004))
+(line (p1 650005) (p2 630005))
+(line (p1 630005) (p2 620005))
+(line (p1 620005) (p2 610005))
+(line (p1 610005) (p2 600004))
+(line (p1 660000) (p2 680000))
+(line (p1 680000) (p2 690000))
+(line (p1 690000) (p2 700000))
+(line (p1 660000) (p2 660002))
+(line (p1 660002) (p2 660003))
+(line (p1 660003) (p2 660004))
+(line (p1 660004) (p2 700004))
+(line (p1 700004) (p2 700000))
+(line (p1 700000) (p2 710001))
+(line (p1 710001) (p2 710002))
+(line (p1 710002) (p2 710003))
+(line (p1 710003) (p2 710005))
+(line (p1 710005) (p2 700004))
+(line (p1 710005) (p2 690005))
+(line (p1 690005) (p2 680005))
+(line (p1 680005) (p2 670005))
+(line (p1 670005) (p2 660004))
+(line (p1 600006) (p2 620006))
+(line (p1 620006) (p2 630006))
+(line (p1 630006) (p2 640006))
+(line (p1 600006) (p2 600008))
+(line (p1 600008) (p2 600009))
+(line (p1 600009) (p2 600010))
+(line (p1 600010) (p2 640010))
+(line (p1 640010) (p2 640006))
+(line (p1 640006) (p2 650007))
+(line (p1 650007) (p2 650008))
+(line (p1 650008) (p2 650009))
+(line (p1 650009) (p2 650011))
+(line (p1 650011) (p2 640010))
+(line (p1 650011) (p2 630011))
+(line (p1 630011) (p2 620011))
+(line (p1 620011) (p2 610011))
+(line (p1 610011) (p2 600010))
+(line (p1 660006) (p2 680006))
+(line (p1 680006) (p2 690006))
+(line (p1 690006) (p2 700006))
+(line (p1 660006) (p2 660008))
+(line (p1 660008) (p2 660009))
+(line (p1 660009) (p2 660010))
+(line (p1 660010) (p2 700010))
+(line (p1 700010) (p2 700006))
+(line (p1 700006) (p2 710007))
+(line (p1 710007) (p2 710008))
+(line (p1 710008) (p2 710009))
+(line (p1 710009) (p2 710011))
+(line (p1 710011) (p2 700010))
+(line (p1 710011) (p2 690011))
+(line (p1 690011) (p2 680011))
+(line (p1 680011) (p2 670011))
+(line (p1 670011) (p2 660010))
+(line (p1 590003) (p2 600003))
+(line (p1 570005) (p2 570006))
+(line (p1 620005) (p2 620006))
+(line (p1 590008) (p2 600008))
+(line (p1 770003) (p2 780003))
+(line (p1 750005) (p2 750006))
+(line (p1 800005) (p2 800006))
+(line (p1 770008) (p2 780008))
+(line (p1 720000) (p2 740000))
+(line (p1 740000) (p2 750000))
+(line (p1 750000) (p2 760000))
+(line (p1 720000) (p2 720002))
+(line (p1 720002) (p2 720003))
+(line (p1 720003) (p2 720004))
+(line (p1 720004) (p2 760004))
+(line (p1 760004) (p2 760000))
+(line (p1 760000) (p2 770001))
+(line (p1 770001) (p2 770002))
+(line (p1 770002) (p2 770003))
+(line (p1 770003) (p2 770005))
+(line (p1 770005) (p2 760004))
+(line (p1 770005) (p2 750005))
+(line (p1 750005) (p2 740005))
+(line (p1 740005) (p2 730005))
+(line (p1 730005) (p2 720004))
+(line (p1 780000) (p2 800000))
+(line (p1 800000) (p2 810000))
+(line (p1 810000) (p2 820000))
+(line (p1 780000) (p2 780002))
+(line (p1 780002) (p2 780003))
+(line (p1 780003) (p2 780004))
+(line (p1 780004) (p2 820004))
+(line (p1 820004) (p2 820000))
+(line (p1 820000) (p2 830001))
+(line (p1 830001) (p2 830002))
+(line (p1 830002) (p2 830003))
+(line (p1 830003) (p2 830005))
+(line (p1 830005) (p2 820004))
+(line (p1 830005) (p2 810005))
+(line (p1 810005) (p2 800005))
+(line (p1 800005) (p2 790005))
+(line (p1 790005) (p2 780004))
+(line (p1 720006) (p2 740006))
+(line (p1 740006) (p2 750006))
+(line (p1 750006) (p2 760006))
+(line (p1 720006) (p2 720008))
+(line (p1 720008) (p2 720009))
+(line (p1 720009) (p2 720010))
+(line (p1 720010) (p2 760010))
+(line (p1 760010) (p2 760006))
+(line (p1 760006) (p2 770007))
+(line (p1 770007) (p2 770008))
+(line (p1 770008) (p2 770009))
+(line (p1 770009) (p2 770011))
+(line (p1 770011) (p2 760010))
+(line (p1 770011) (p2 750011))
+(line (p1 750011) (p2 740011))
+(line (p1 740011) (p2 730011))
+(line (p1 730011) (p2 720010))
+(line (p1 780006) (p2 800006))
+(line (p1 800006) (p2 810006))
+(line (p1 810006) (p2 820006))
+(line (p1 780006) (p2 780008))
+(line (p1 780008) (p2 780009))
+(line (p1 780009) (p2 780010))
+(line (p1 780010) (p2 820010))
+(line (p1 820010) (p2 820006))
+(line (p1 820006) (p2 830007))
+(line (p1 830007) (p2 830008))
+(line (p1 830008) (p2 830009))
+(line (p1 830009) (p2 830011))
+(line (p1 830011) (p2 820010))
+(line (p1 830011) (p2 810011))
+(line (p1 810011) (p2 800011))
+(line (p1 800011) (p2 790011))
+(line (p1 790011) (p2 780010))
+(line (p1 710003) (p2 720003))
+(line (p1 690005) (p2 690006))
+(line (p1 740005) (p2 740006))
+(line (p1 710008) (p2 720008))
+(line (p1 890003) (p2 900003))
+(line (p1 870005) (p2 870006))
+(line (p1 920005) (p2 920006))
+(line (p1 890008) (p2 900008))
+(line (p1 840000) (p2 860000))
+(line (p1 860000) (p2 870000))
+(line (p1 870000) (p2 880000))
+(line (p1 840000) (p2 840002))
+(line (p1 840002) (p2 840003))
+(line (p1 840003) (p2 840004))
+(line (p1 840004) (p2 880004))
+(line (p1 880004) (p2 880000))
+(line (p1 880000) (p2 890001))
+(line (p1 890001) (p2 890002))
+(line (p1 890002) (p2 890003))
+(line (p1 890003) (p2 890005))
+(line (p1 890005) (p2 880004))
+(line (p1 890005) (p2 870005))
+(line (p1 870005) (p2 860005))
+(line (p1 860005) (p2 850005))
+(line (p1 850005) (p2 840004))
+(line (p1 900000) (p2 920000))
+(line (p1 920000) (p2 930000))
+(line (p1 930000) (p2 940000))
+(line (p1 900000) (p2 900002))
+(line (p1 900002) (p2 900003))
+(line (p1 900003) (p2 900004))
+(line (p1 900004) (p2 940004))
+(line (p1 940004) (p2 940000))
+(line (p1 940000) (p2 950001))
+(line (p1 950001) (p2 950002))
+(line (p1 950002) (p2 950003))
+(line (p1 950003) (p2 950005))
+(line (p1 950005) (p2 940004))
+(line (p1 950005) (p2 930005))
+(line (p1 930005) (p2 920005))
+(line (p1 920005) (p2 910005))
+(line (p1 910005) (p2 900004))
+(line (p1 840006) (p2 860006))
+(line (p1 860006) (p2 870006))
+(line (p1 870006) (p2 880006))
+(line (p1 840006) (p2 840008))
+(line (p1 840008) (p2 840009))
+(line (p1 840009) (p2 840010))
+(line (p1 840010) (p2 880010))
+(line (p1 880010) (p2 880006))
+(line (p1 880006) (p2 890007))
+(line (p1 890007) (p2 890008))
+(line (p1 890008) (p2 890009))
+(line (p1 890009) (p2 890011))
+(line (p1 890011) (p2 880010))
+(line (p1 890011) (p2 870011))
+(line (p1 870011) (p2 860011))
+(line (p1 860011) (p2 850011))
+(line (p1 850011) (p2 840010))
+(line (p1 900006) (p2 920006))
+(line (p1 920006) (p2 930006))
+(line (p1 930006) (p2 940006))
+(line (p1 900006) (p2 900008))
+(line (p1 900008) (p2 900009))
+(line (p1 900009) (p2 900010))
+(line (p1 900010) (p2 940010))
+(line (p1 940010) (p2 940006))
+(line (p1 940006) (p2 950007))
+(line (p1 950007) (p2 950008))
+(line (p1 950008) (p2 950009))
+(line (p1 950009) (p2 950011))
+(line (p1 950011) (p2 940010))
+(line (p1 950011) (p2 930011))
+(line (p1 930011) (p2 920011))
+(line (p1 920011) (p2 910011))
+(line (p1 910011) (p2 900010))
+(line (p1 830003) (p2 840003))
+(line (p1 810005) (p2 810006))
+(line (p1 860005) (p2 860006))
+(line (p1 830008) (p2 840008))
+(line (p1 1010003) (p2 1020003))
+(line (p1 990005) (p2 990006))
+(line (p1 1040005) (p2 1040006))
+(line (p1 1010008) (p2 1020008))
+(line (p1 960000) (p2 980000))
+(line (p1 980000) (p2 990000))
+(line (p1 990000) (p2 1000000))
+(line (p1 960000) (p2 960002))
+(line (p1 960002) (p2 960003))
+(line (p1 960003) (p2 960004))
+(line (p1 960004) (p2 1000004))
+(line (p1 1000004) (p2 1000000))
+(line (p1 1000000) (p2 1010001))
+(line (p1 1010001) (p2 1010002))
+(line (p1 1010002) (p2 1010003))
+(line (p1 1010003) (p2 1010005))
+(line (p1 1010005) (p2 1000004))
+(line (p1 1010005) (p2 990005))
+(line (p1 990005) (p2 980005))
+(line (p1 980005) (p2 970005))
+(line (p1 970005) (p2 960004))
+(line (p1 1020000) (p2 1040000))
+(line (p1 1040000) (p2 1050000))
+(line (p1 1050000) (p2 1060000))
+(line (p1 1020000) (p2 1020002))
+(line (p1 1020002) (p2 1020003))
+(line (p1 1020003) (p2 1020004))
+(line (p1 1020004) (p2 1060004))
+(line (p1 1060004) (p2 1060000))
+(line (p1 1060000) (p2 1070001))
+(line (p1 1070001) (p2 1070002))
+(line (p1 1070002) (p2 1070003))
+(line (p1 1070003) (p2 1070005))
+(line (p1 1070005) (p2 1060004))
+(line (p1 1070005) (p2 1050005))
+(line (p1 1050005) (p2 1040005))
+(line (p1 1040005) (p2 1030005))
+(line (p1 1030005) (p2 1020004))
+(line (p1 960006) (p2 980006))
+(line (p1 980006) (p2 990006))
+(line (p1 990006) (p2 1000006))
+(line (p1 960006) (p2 960008))
+(line (p1 960008) (p2 960009))
+(line (p1 960009) (p2 960010))
+(line (p1 960010) (p2 1000010))
+(line (p1 1000010) (p2 1000006))
+(line (p1 1000006) (p2 1010007))
+(line (p1 1010007) (p2 1010008))
+(line (p1 1010008) (p2 1010009))
+(line (p1 1010009) (p2 1010011))
+(line (p1 1010011) (p2 1000010))
+(line (p1 1010011) (p2 990011))
+(line (p1 990011) (p2 980011))
+(line (p1 980011) (p2 970011))
+(line (p1 970011) (p2 960010))
+(line (p1 1020006) (p2 1040006))
+(line (p1 1040006) (p2 1050006))
+(line (p1 1050006) (p2 1060006))
+(line (p1 1020006) (p2 1020008))
+(line (p1 1020008) (p2 1020009))
+(line (p1 1020009) (p2 1020010))
+(line (p1 1020010) (p2 1060010))
+(line (p1 1060010) (p2 1060006))
+(line (p1 1060006) (p2 1070007))
+(line (p1 1070007) (p2 1070008))
+(line (p1 1070008) (p2 1070009))
+(line (p1 1070009) (p2 1070011))
+(line (p1 1070011) (p2 1060010))
+(line (p1 1070011) (p2 1050011))
+(line (p1 1050011) (p2 1040011))
+(line (p1 1040011) (p2 1030011))
+(line (p1 1030011) (p2 1020010))
+(line (p1 950003) (p2 960003))
+(line (p1 930005) (p2 930006))
+(line (p1 980005) (p2 980006))
+(line (p1 950008) (p2 960008))
+(line (p1 1130003) (p2 1140003))
+(line (p1 1110005) (p2 1110006))
+(line (p1 1160005) (p2 1160006))
+(line (p1 1130008) (p2 1140008))
+(line (p1 1080000) (p2 1100000))
+(line (p1 1100000) (p2 1110000))
+(line (p1 1110000) (p2 1120000))
+(line (p1 1080000) (p2 1080002))
+(line (p1 1080002) (p2 1080003))
+(line (p1 1080003) (p2 1080004))
+(line (p1 1080004) (p2 1120004))
+(line (p1 1120004) (p2 1120000))
+(line (p1 1120000) (p2 1130001))
+(line (p1 1130001) (p2 1130002))
+(line (p1 1130002) (p2 1130003))
+(line (p1 1130003) (p2 1130005))
+(line (p1 1130005) (p2 1120004))
+(line (p1 1130005) (p2 1110005))
+(line (p1 1110005) (p2 1100005))
+(line (p1 1100005) (p2 1090005))
+(line (p1 1090005) (p2 1080004))
+(line (p1 1140000) (p2 1160000))
+(line (p1 1160000) (p2 1170000))
+(line (p1 1170000) (p2 1180000))
+(line (p1 1140000) (p2 1140002))
+(line (p1 1140002) (p2 1140003))
+(line (p1 1140003) (p2 1140004))
+(line (p1 1140004) (p2 1180004))
+(line (p1 1180004) (p2 1180000))
+(line (p1 1180000) (p2 1190001))
+(line (p1 1190001) (p2 1190002))
+(line (p1 1190002) (p2 1190003))
+(line (p1 1190003) (p2 1190005))
+(line (p1 1190005) (p2 1180004))
+(line (p1 1190005) (p2 1170005))
+(line (p1 1170005) (p2 1160005))
+(line (p1 1160005) (p2 1150005))
+(line (p1 1150005) (p2 1140004))
+(line (p1 1080006) (p2 1100006))
+(line (p1 1100006) (p2 1110006))
+(line (p1 1110006) (p2 1120006))
+(line (p1 1080006) (p2 1080008))
+(line (p1 1080008) (p2 1080009))
+(line (p1 1080009) (p2 1080010))
+(line (p1 1080010) (p2 1120010))
+(line (p1 1120010) (p2 1120006))
+(line (p1 1120006) (p2 1130007))
+(line (p1 1130007) (p2 1130008))
+(line (p1 1130008) (p2 1130009))
+(line (p1 1130009) (p2 1130011))
+(line (p1 1130011) (p2 1120010))
+(line (p1 1130011) (p2 1110011))
+(line (p1 1110011) (p2 1100011))
+(line (p1 1100011) (p2 1090011))
+(line (p1 1090011) (p2 1080010))
+(line (p1 1140006) (p2 1160006))
+(line (p1 1160006) (p2 1170006))
+(line (p1 1170006) (p2 1180006))
+(line (p1 1140006) (p2 1140008))
+(line (p1 1140008) (p2 1140009))
+(line (p1 1140009) (p2 1140010))
+(line (p1 1140010) (p2 1180010))
+(line (p1 1180010) (p2 1180006))
+(line (p1 1180006) (p2 1190007))
+(line (p1 1190007) (p2 1190008))
+(line (p1 1190008) (p2 1190009))
+(line (p1 1190009) (p2 1190011))
+(line (p1 1190011) (p2 1180010))
+(line (p1 1190011) (p2 1170011))
+(line (p1 1170011) (p2 1160011))
+(line (p1 1160011) (p2 1150011))
+(line (p1 1150011) (p2 1140010))
+(line (p1 1070003) (p2 1080003))
+(line (p1 1050005) (p2 1050006))
+(line (p1 1100005) (p2 1100006))
+(line (p1 1070008) (p2 1080008))
+(line (p1 1250003) (p2 1260003))
+(line (p1 1230005) (p2 1230006))
+(line (p1 1280005) (p2 1280006))
+(line (p1 1250008) (p2 1260008))
+(line (p1 1200000) (p2 1220000))
+(line (p1 1220000) (p2 1230000))
+(line (p1 1230000) (p2 1240000))
+(line (p1 1200000) (p2 1200002))
+(line (p1 1200002) (p2 1200003))
+(line (p1 1200003) (p2 1200004))
+(line (p1 1200004) (p2 1240004))
+(line (p1 1240004) (p2 1240000))
+(line (p1 1240000) (p2 1250001))
+(line (p1 1250001) (p2 1250002))
+(line (p1 1250002) (p2 1250003))
+(line (p1 1250003) (p2 1250005))
+(line (p1 1250005) (p2 1240004))
+(line (p1 1250005) (p2 1230005))
+(line (p1 1230005) (p2 1220005))
+(line (p1 1220005) (p2 1210005))
+(line (p1 1210005) (p2 1200004))
+(line (p1 1260000) (p2 1280000))
+(line (p1 1280000) (p2 1290000))
+(line (p1 1290000) (p2 1300000))
+(line (p1 1260000) (p2 1260002))
+(line (p1 1260002) (p2 1260003))
+(line (p1 1260003) (p2 1260004))
+(line (p1 1260004) (p2 1300004))
+(line (p1 1300004) (p2 1300000))
+(line (p1 1300000) (p2 1310001))
+(line (p1 1310001) (p2 1310002))
+(line (p1 1310002) (p2 1310003))
+(line (p1 1310003) (p2 1310005))
+(line (p1 1310005) (p2 1300004))
+(line (p1 1310005) (p2 1290005))
+(line (p1 1290005) (p2 1280005))
+(line (p1 1280005) (p2 1270005))
+(line (p1 1270005) (p2 1260004))
+(line (p1 1200006) (p2 1220006))
+(line (p1 1220006) (p2 1230006))
+(line (p1 1230006) (p2 1240006))
+(line (p1 1200006) (p2 1200008))
+(line (p1 1200008) (p2 1200009))
+(line (p1 1200009) (p2 1200010))
+(line (p1 1200010) (p2 1240010))
+(line (p1 1240010) (p2 1240006))
+(line (p1 1240006) (p2 1250007))
+(line (p1 1250007) (p2 1250008))
+(line (p1 1250008) (p2 1250009))
+(line (p1 1250009) (p2 1250011))
+(line (p1 1250011) (p2 1240010))
+(line (p1 1250011) (p2 1230011))
+(line (p1 1230011) (p2 1220011))
+(line (p1 1220011) (p2 1210011))
+(line (p1 1210011) (p2 1200010))
+(line (p1 1260006) (p2 1280006))
+(line (p1 1280006) (p2 1290006))
+(line (p1 1290006) (p2 1300006))
+(line (p1 1260006) (p2 1260008))
+(line (p1 1260008) (p2 1260009))
+(line (p1 1260009) (p2 1260010))
+(line (p1 1260010) (p2 1300010))
+(line (p1 1300010) (p2 1300006))
+(line (p1 1300006) (p2 1310007))
+(line (p1 1310007) (p2 1310008))
+(line (p1 1310008) (p2 1310009))
+(line (p1 1310009) (p2 1310011))
+(line (p1 1310011) (p2 1300010))
+(line (p1 1310011) (p2 1290011))
+(line (p1 1290011) (p2 1280011))
+(line (p1 1280011) (p2 1270011))
+(line (p1 1270011) (p2 1260010))
+(line (p1 1190003) (p2 1200003))
+(line (p1 1170005) (p2 1170006))
+(line (p1 1220005) (p2 1220006))
+(line (p1 1190008) (p2 1200008))
+(line (p1 1370003) (p2 1380003))
+(line (p1 1350005) (p2 1350006))
+(line (p1 1400005) (p2 1400006))
+(line (p1 1370008) (p2 1380008))
+(line (p1 1320000) (p2 1340000))
+(line (p1 1340000) (p2 1350000))
+(line (p1 1350000) (p2 1360000))
+(line (p1 1320000) (p2 1320002))
+(line (p1 1320002) (p2 1320003))
+(line (p1 1320003) (p2 1320004))
+(line (p1 1320004) (p2 1360004))
+(line (p1 1360004) (p2 1360000))
+(line (p1 1360000) (p2 1370001))
+(line (p1 1370001) (p2 1370002))
+(line (p1 1370002) (p2 1370003))
+(line (p1 1370003) (p2 1370005))
+(line (p1 1370005) (p2 1360004))
+(line (p1 1370005) (p2 1350005))
+(line (p1 1350005) (p2 1340005))
+(line (p1 1340005) (p2 1330005))
+(line (p1 1330005) (p2 1320004))
+(line (p1 1380000) (p2 1400000))
+(line (p1 1400000) (p2 1410000))
+(line (p1 1410000) (p2 1420000))
+(line (p1 1380000) (p2 1380002))
+(line (p1 1380002) (p2 1380003))
+(line (p1 1380003) (p2 1380004))
+(line (p1 1380004) (p2 1420004))
+(line (p1 1420004) (p2 1420000))
+(line (p1 1420000) (p2 1430001))
+(line (p1 1430001) (p2 1430002))
+(line (p1 1430002) (p2 1430003))
+(line (p1 1430003) (p2 1430005))
+(line (p1 1430005) (p2 1420004))
+(line (p1 1430005) (p2 1410005))
+(line (p1 1410005) (p2 1400005))
+(line (p1 1400005) (p2 1390005))
+(line (p1 1390005) (p2 1380004))
+(line (p1 1320006) (p2 1340006))
+(line (p1 1340006) (p2 1350006))
+(line (p1 1350006) (p2 1360006))
+(line (p1 1320006) (p2 1320008))
+(line (p1 1320008) (p2 1320009))
+(line (p1 1320009) (p2 1320010))
+(line (p1 1320010) (p2 1360010))
+(line (p1 1360010) (p2 1360006))
+(line (p1 1360006) (p2 1370007))
+(line (p1 1370007) (p2 1370008))
+(line (p1 1370008) (p2 1370009))
+(line (p1 1370009) (p2 1370011))
+(line (p1 1370011) (p2 1360010))
+(line (p1 1370011) (p2 1350011))
+(line (p1 1350011) (p2 1340011))
+(line (p1 1340011) (p2 1330011))
+(line (p1 1330011) (p2 1320010))
+(line (p1 1380006) (p2 1400006))
+(line (p1 1400006) (p2 1410006))
+(line (p1 1410006) (p2 1420006))
+(line (p1 1380006) (p2 1380008))
+(line (p1 1380008) (p2 1380009))
+(line (p1 1380009) (p2 1380010))
+(line (p1 1380010) (p2 1420010))
+(line (p1 1420010) (p2 1420006))
+(line (p1 1420006) (p2 1430007))
+(line (p1 1430007) (p2 1430008))
+(line (p1 1430008) (p2 1430009))
+(line (p1 1430009) (p2 1430011))
+(line (p1 1430011) (p2 1420010))
+(line (p1 1430011) (p2 1410011))
+(line (p1 1410011) (p2 1400011))
+(line (p1 1400011) (p2 1390011))
+(line (p1 1390011) (p2 1380010))
+(line (p1 1310003) (p2 1320003))
+(line (p1 1290005) (p2 1290006))
+(line (p1 1340005) (p2 1340006))
+(line (p1 1310008) (p2 1320008))
+(line (p1 1490003) (p2 1500003))
+(line (p1 1470005) (p2 1470006))
+(line (p1 1520005) (p2 1520006))
+(line (p1 1490008) (p2 1500008))
+(line (p1 1440000) (p2 1460000))
+(line (p1 1460000) (p2 1470000))
+(line (p1 1470000) (p2 1480000))
+(line (p1 1440000) (p2 1440002))
+(line (p1 1440002) (p2 1440003))
+(line (p1 1440003) (p2 1440004))
+(line (p1 1440004) (p2 1480004))
+(line (p1 1480004) (p2 1480000))
+(line (p1 1480000) (p2 1490001))
+(line (p1 1490001) (p2 1490002))
+(line (p1 1490002) (p2 1490003))
+(line (p1 1490003) (p2 1490005))
+(line (p1 1490005) (p2 1480004))
+(line (p1 1490005) (p2 1470005))
+(line (p1 1470005) (p2 1460005))
+(line (p1 1460005) (p2 1450005))
+(line (p1 1450005) (p2 1440004))
+(line (p1 1500000) (p2 1520000))
+(line (p1 1520000) (p2 1530000))
+(line (p1 1530000) (p2 1540000))
+(line (p1 1500000) (p2 1500002))
+(line (p1 1500002) (p2 1500003))
+(line (p1 1500003) (p2 1500004))
+(line (p1 1500004) (p2 1540004))
+(line (p1 1540004) (p2 1540000))
+(line (p1 1540000) (p2 1550001))
+(line (p1 1550001) (p2 1550002))
+(line (p1 1550002) (p2 1550003))
+(line (p1 1550003) (p2 1550005))
+(line (p1 1550005) (p2 1540004))
+(line (p1 1550005) (p2 1530005))
+(line (p1 1530005) (p2 1520005))
+(line (p1 1520005) (p2 1510005))
+(line (p1 1510005) (p2 1500004))
+(line (p1 1440006) (p2 1460006))
+(line (p1 1460006) (p2 1470006))
+(line (p1 1470006) (p2 1480006))
+(line (p1 1440006) (p2 1440008))
+(line (p1 1440008) (p2 1440009))
+(line (p1 1440009) (p2 1440010))
+(line (p1 1440010) (p2 1480010))
+(line (p1 1480010) (p2 1480006))
+(line (p1 1480006) (p2 1490007))
+(line (p1 1490007) (p2 1490008))
+(line (p1 1490008) (p2 1490009))
+(line (p1 1490009) (p2 1490011))
+(line (p1 1490011) (p2 1480010))
+(line (p1 1490011) (p2 1470011))
+(line (p1 1470011) (p2 1460011))
+(line (p1 1460011) (p2 1450011))
+(line (p1 1450011) (p2 1440010))
+(line (p1 1500006) (p2 1520006))
+(line (p1 1520006) (p2 1530006))
+(line (p1 1530006) (p2 1540006))
+(line (p1 1500006) (p2 1500008))
+(line (p1 1500008) (p2 1500009))
+(line (p1 1500009) (p2 1500010))
+(line (p1 1500010) (p2 1540010))
+(line (p1 1540010) (p2 1540006))
+(line (p1 1540006) (p2 1550007))
+(line (p1 1550007) (p2 1550008))
+(line (p1 1550008) (p2 1550009))
+(line (p1 1550009) (p2 1550011))
+(line (p1 1550011) (p2 1540010))
+(line (p1 1550011) (p2 1530011))
+(line (p1 1530011) (p2 1520011))
+(line (p1 1520011) (p2 1510011))
+(line (p1 1510011) (p2 1500010))
+(line (p1 1430003) (p2 1440003))
+(line (p1 1410005) (p2 1410006))
+(line (p1 1460005) (p2 1460006))
+(line (p1 1430008) (p2 1440008))




More information about the jboss-svn-commits mailing list