[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 < <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("Hello world!");
+ * }
+ * }
+ * </pre>
+ *
+ * can be generated as follows:
+ *
+ * <pre>
+ * ClassWriter cw = new ClassWriter(true);
+ * cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);
+ *
+ * Method m = Method.getMethod("void <init> ()");
+ * 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("void main (String[])");
+ * mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw);
+ * mg.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class));
+ * mg.push("Hello world!");
+ * mg.invokeVirtual(Type.getType(PrintStream.class), Method.getMethod("void println (String)"));
+ * 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, <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.
+ * 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.
+ * 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] >>> 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;
+ * </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,
+ * "Hello",
+ * null,
+ * "java/lang/Object",
+ * null);
+ *
+ * cw.visitSource("Hello.java", null);
+ *
+ * {
+ * mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ * mv.visitVarInsn(ALOAD, 0);
+ * mv.visitMethodInsn(INVOKESPECIAL,
+ * "java/lang/Object",
+ * "<init>",
+ * "()V");
+ * mv.visitInsn(RETURN);
+ * mv.visitMaxs(1, 1);
+ * mv.visitEnd();
+ * }
+ * {
+ * mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC,
+ * "main",
+ * "([Ljava/lang/String;)V",
+ * null,
+ * null);
+ * mv.visitFieldInsn(GETSTATIC,
+ * "java/lang/System",
+ * "out",
+ * "Ljava/io/PrintStream;");
+ * mv.visitLdcInsn("hello");
+ * mv.visitMethodInsn(INVOKEVIRTUAL,
+ * "java/io/PrintStream",
+ * "println",
+ * "(Ljava/lang/String;)V");
+ * 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("hello");
+ * }
+ * }
+ * </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] <fully qualified
+ * class name or class file name>
+ *
+ * @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
+ * '<init>' or '<clinit>'.
+ *
+ * @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 <init> ()V
+ * ALOAD 0
+ * INVOKESPECIAL java/lang/Object <init> ()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 "hello"
+ * 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("hello");
+ * }
+ * }
+ * </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] <fully qualified class name or class
+ * file name >
+ *
+ * @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 <= <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 < 0 or index > 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 <= 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 < 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( "seat 1 " + guest.getName() + " );
+ *
+ * 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( "seat " + rightSeat + " " + rightSeatName + " " + 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 "cheddar") )
+ *
+ *
+ * </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&:(= ?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 >(* 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 == "cheddar" && price > 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 == "cheddar" || price > 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 == "cheddar" && price > 10) || ( type == "e;stilton"e; && price < 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