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 = ValueType.OBJECT_TYPE.getEvaluator(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 AlphaMemory memory = (AlphaMemory) workingMemory.getNodeMemory(alphaNode); assertNull(memory.facts); // object should assert as it passes text alphaNode.assertObject(f0, context, workingMemory); assertEquals(1, sink.getAsserted().size()); assertNull(memory.facts); 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()); assertNull(memory.facts); list = (Object[]) sink.getAsserted().get(0); assertSame(cheddar, workingMemory.getObject((DefaultFactHandle) list[0])); }
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 = ValueType.OBJECT_TYPE.getEvaluator(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 AlphaMemory memory = (AlphaMemory) workingMemory.getNodeMemory(alphaNode); assertEquals(0, memory.facts.size()); // object should assert as it passes text alphaNode.assertObject(f0, context, workingMemory); assertEquals(1, memory.facts.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.facts.size()); assertTrue("Should contain 'cheddar handle'", memory.facts.contains(f0)); // object should retract as it does exist alphaNode.retractObject(f0, context, workingMemory); assertLength(1, sink.getRetracted()); assertEquals(0, memory.facts.size()); final Object[] list = (Object[]) sink.getRetracted().get(0); assertSame(f0, list[0]); }
/** * 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 LeftTupleSource source, final BuildContext context) { super( id, context.getPartitionId(), context.getRuleBase().getConfiguration().isMultithreadEvaluation()); this.tupleSource = source; this.tupleMemoryEnabled = context.isTupleMemoryEnabled(); }
@Test public void testLiteralConstraintAssertObjectWithoutMemory() throws Exception { ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase(); 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.INSERTION, null, null, null); final MockObjectSource source = new MockObjectSource(buildContext.getNextId()); final ClassFieldReader extractor = store.getReader(Cheese.class, "type", getClass().getClassLoader()); final FieldValue field = FieldFactory.getInstance().getFieldValue("cheddar"); final MvelConstraint constraint = new MvelConstraintTestUtil("type == \"cheddar\"", field, extractor); // 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 AlphaMemory memory = (AlphaMemory) workingMemory.getNodeMemory(alphaNode); // object should assert as it passes text alphaNode.assertObject(f0, context, workingMemory); assertEquals(1, sink.getAsserted().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()); list = (Object[]) sink.getAsserted().get(0); assertSame(cheddar, workingMemory.getObject((DefaultFactHandle) list[0])); }
public EntryPointNode(final int id, final ObjectSource objectSource, final BuildContext context) { this( id, context.getPartitionId(), context.getRuleBase().getConfiguration().isMultithreadEvaluation(), objectSource, context .getCurrentEntryPoint()); // irrelevant for this node, since it overrides sink // management }
/* * 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 = ValueType.OBJECT_TYPE.getEvaluator(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()); }
/** * 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 */ public LeftInputAdapterNode(final int id, final ObjectSource source, final BuildContext context) { super( id, context.getPartitionId(), context.getRuleBase().getConfiguration().isMultithreadEvaluation()); this.objectSource = source; this.leftTupleMemoryEnabled = context.isTupleMemoryEnabled(); ObjectSource current = source; while (!(current instanceof ObjectTypeNode)) { current = current.getParentObjectSource(); } ObjectTypeNode otn = (ObjectTypeNode) current; rootQueryNode = ClassObjectType.DroolsQuery_ObjectType.isAssignableFrom(otn.getObjectType()); }
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 = ValueType.OBJECT_TYPE.getEvaluator(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 AlphaMemory memory = (AlphaMemory) workingMemory.getNodeMemory(alphaNode); assertNull(memory.facts); // 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 assertNull(memory.facts); }
/** * 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, context.getPartitionId(), context.getRuleBase().getConfiguration().isMultithreadEvaluation(), source, context.getRuleBase().getConfiguration().getAlphaNodeHashingThreshold()); this.objectType = objectType; setObjectMemoryEnabled(context.isObjectTypeNodeMemoryEnabled()); }
public BuildContext createContext() { RuleBaseConfiguration conf = new RuleBaseConfiguration(); ReteooRuleBase rbase = new ReteooRuleBase("ID", conf); BuildContext buildContext = new BuildContext(rbase, rbase.getReteooBuilder().getIdGenerator()); Rule rule = new Rule("rule1", "org.pkg1", null); org.drools.rule.Package pkg = new org.drools.rule.Package("org.pkg1"); pkg.getDialectRuntimeRegistry().setDialectData("mvel", new MVELDialectRuntimeData()); pkg.addRule(rule); buildContext.setRule(rule); return buildContext; }
public void attach(BuildContext context) { constraints.init(context, getType()); setUnificationJoin(); this.rightInput.addObjectSink(this); this.leftInput.addTupleSink(this, context); if (context == null) { return; } for (InternalWorkingMemory workingMemory : context.getWorkingMemories()) { final PropagationContext propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(), PropagationContext.RULE_ADDITION, null, null, null); /* FIXME: This should be generalized at BetaNode level and the * instanceof should be removed! * * When L&R Unlinking is enabled, we only need to update the side * that is initially linked. If there are tuples to be propagated, * they will trigger the update (thus, population) of the other side. * */ if (!lrUnlinkingEnabled || !(this instanceof JoinNode)) { this.rightInput.updateSink(this, propagationContext, workingMemory); } this.leftInput.updateSink(this, propagationContext, workingMemory); } }
public void setupJoinNode() { buildContext = createContext(); joinNode = (JoinNode) BetaNodeBuilder.create(NodeTypeEnums.JoinNode, buildContext) .setLeftType(A.class) .setBinding("object", "$object") .setRightType(B.class) .setConstraint("object", "!=", "$object") .build(); sinkNode = new JoinNode(); sinkNode.setId(1); sinkNode.setConstraints(new EmptyBetaConstraints()); joinNode.addTupleSink(sinkNode); wm = (InternalWorkingMemory) buildContext.getRuleBase().newStatefulSession(true); bm = (BetaMemory) wm.getNodeMemory(joinNode); bm0 = (BetaMemory) wm.getNodeMemory(sinkNode); smem = new SegmentMemory(joinNode); bm.setSegmentMemory(smem); smem0 = new SegmentMemory(sinkNode); bm0.setSegmentMemory(smem0); smem.add(smem0); }
/** * 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 LeftTupleSource leftInput, final ObjectSource rightInput, final BetaConstraints joinNodeBinder, final BuildContext context) { super( id, context.getPartitionId(), context.getRuleBase().getConfiguration().isMultithreadEvaluation(), leftInput, rightInput, joinNodeBinder, context); this.tupleMemoryEnabled = context.isTupleMemoryEnabled(); }
public QueryElementNode( final int id, final LeftTupleSource tupleSource, final QueryElement queryElement, final boolean tupleMemoryEnabled, final boolean openQuery, final BuildContext context) { super( id, context.getPartitionId(), context.getRuleBase().getConfiguration().isMultithreadEvaluation()); this.tupleSource = tupleSource; this.queryElement = queryElement; this.tupleMemoryEnabled = tupleMemoryEnabled; this.openQuery = openQuery; initMasks(context, tupleSource); }
/** * 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, context.getPartitionId(), context.getRuleBase().getConfiguration().isMultithreadEvaluation(), source, context.getRuleBase().getConfiguration().getAlphaNodeHashingThreshold()); this.objectType = objectType; this.lrUnlinkingEnabled = context.getRuleBase().getConfiguration().isLRUnlinkingEnabled(); setObjectMemoryEnabled(context.isObjectTypeNodeMemoryEnabled()); if (ClassObjectType.DroolsQuery_ObjectType.isAssignableFrom(objectType)) { queryNode = true; } }
@Override protected void initDeclaredMask(BuildContext context, LeftTupleSource leftInput) { if (context == null || context.getLastBuiltPatterns() == null) { // only happens during unit tests rightDeclaredMask = Long.MAX_VALUE; super.initDeclaredMask(context, leftInput); return; } if (!(rightInput instanceof RightInputAdapterNode)) { Pattern pattern = context.getLastBuiltPatterns()[0]; // right input pattern ObjectType objectType = pattern.getObjectType(); if (!(objectType instanceof ClassObjectType)) { // InitialFact has no type declaration and cannot be property specific // Only ClassObjectType can use property specific rightDeclaredMask = Long.MAX_VALUE; } Class objectClass = ((ClassObjectType) objectType).getClassType(); if (isPropertyReactive(context, objectClass)) { rightListenedProperties = pattern.getListenedProperties(); List<String> settableProperties = getSettableProperties(context.getRuleBase(), objectClass); rightDeclaredMask = calculatePositiveMask(rightListenedProperties, settableProperties); rightDeclaredMask |= constraints.getListenedPropertyMask(settableProperties); rightNegativeMask = calculateNegativeMask(rightListenedProperties, settableProperties); } else { // if property reactive is not on, then accept all modification propagations rightDeclaredMask = Long.MAX_VALUE; } } else { rightDeclaredMask = Long.MAX_VALUE; // There would have been no right input pattern, so swap current to first, so leftInput can // still work context.setLastBuiltPattern(context.getLastBuiltPatterns()[0]); } super.initDeclaredMask(context, leftInput); }
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 ClassFieldExtractor extractor = cache.getExtractor(Cheese.class, "type", getClass().getClassLoader()); final FieldValue field = FieldFactory.getFieldValue("cheddar"); final Evaluator evaluator = ValueType.OBJECT_TYPE.getEvaluator(Operator.EQUAL); final LiteralConstraint constraint = new LiteralConstraint(extractor, evaluator, field); final AlphaNode alphaNode = new AlphaNode(buildContext.getNextId(), constraint, null, buildContext); final AlphaMemory memory = (AlphaMemory) workingMemory.getNodeMemory(alphaNode); assertNotNull(memory); }
public AccumulateNode( final int id, final LeftTupleSource leftInput, final ObjectSource rightInput, final AlphaNodeFieldConstraint[] resultConstraints, final BetaConstraints sourceBinder, final BetaConstraints resultBinder, final Accumulate accumulate, final boolean unwrapRightObject, final BuildContext context) { super( id, context.getPartitionId(), context.getRuleBase().getConfiguration().isMultithreadEvaluation(), leftInput, rightInput, sourceBinder, context); this.resultBinder = resultBinder; this.resultConstraints = resultConstraints; this.accumulate = accumulate; this.unwrapRightObject = unwrapRightObject; this.tupleMemoryEnabled = context.isTupleMemoryEnabled(); }
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 = ValueType.OBJECT_TYPE.getEvaluator(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()); }
/** * Test just tuple assertions * * @throws AssertionException */ @Test 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", null, null, null); final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory .getFactHandleFactory() .newFactHandle("other cheese", null, null, null); final LeftTupleImpl tuple0 = new LeftTupleImpl(f0, null, true); 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.assertLeftTuple( tuple0, new PropagationContextImpl(0, PropagationContext.ASSERTION, null, null, f0), this.workingMemory); // check memories assertNull(this.memory.getLeftTupleMemory()); assertEquals(2, this.memory.getRightTupleMemory().size()); assertEquals( "Wrong number of elements in matching objects list ", 2, this.accumulator.getMatchingObjects().size()); // assert tuple, should not add left memory final LeftTupleImpl tuple1 = new LeftTupleImpl(f1, null, true); this.node.assertLeftTuple( tuple1, new PropagationContextImpl(0, PropagationContext.ASSERTION, null, null, f1), this.workingMemory); assertNull(this.memory.getLeftTupleMemory()); assertEquals( "Wrong number of elements in matching objects list ", 2, this.accumulator.getMatchingObjects().size()); assertEquals("Two tuples should have been propagated", 2, this.sink.getAsserted().size()); }
public void execute(Map<String, Object> context, List<String[]> args) { BuildContext buildContext = (BuildContext) context.get("BuildContext"); if (args.size() >= 1) { // The first argument list is the node parameters String[] a = args.get(0); String name = a[0]; String leftInput = a[1]; String rightInput = a[2]; String sourceType = a[3]; String expr = a[4]; LeftTupleSource leftTupleSource; if ("mock".equals(leftInput)) { leftTupleSource = Mockito.mock(LeftTupleSource.class); } else { leftTupleSource = (LeftTupleSource) context.get(leftInput); } ObjectSource rightObjectSource; if ("mock".equals(rightInput)) { rightObjectSource = Mockito.mock(ObjectSource.class); } else { rightObjectSource = (ObjectSource) context.get(rightInput); } Pattern sourcePattern; Pattern resultPattern; try { sourcePattern = reteTesterHelper.getPattern(0, sourceType); // we always use the accumulate function "sum", so return type is always Number resultPattern = reteTesterHelper.getPattern(buildContext.getNextId(), Number.class.getName()); } catch (Exception e) { throw new IllegalArgumentException( "Not possible to process arguments: " + Arrays.toString(a)); } BetaConstraints betaSourceConstraints = new EmptyBetaConstraints(); AlphaNodeFieldConstraint[] alphaResultConstraint = new AlphaNodeFieldConstraint[0]; // the following arguments are constraints for (int i = 1; i < args.size(); i++) { a = args.get(i); String type = a[0]; String fieldName = a[1]; String operator = a[2]; String val = a[3]; if ("source".equals(type)) { Declaration declr = (Declaration) context.get(val); try { BetaNodeFieldConstraint sourceBetaConstraint = this.reteTesterHelper.getBoundVariableConstraint( sourcePattern, fieldName, declr, operator); betaSourceConstraints = new SingleBetaConstraints( sourceBetaConstraint, buildContext.getRuleBase().getConfiguration()); } catch (IntrospectionException e) { throw new IllegalArgumentException(); } } else if ("result".equals(type)) { alphaResultConstraint = new AlphaNodeFieldConstraint[1]; try { alphaResultConstraint[0] = this.reteTesterHelper.getLiteralConstraint(resultPattern, fieldName, operator, val); } catch (IntrospectionException e) { throw new IllegalArgumentException( "Unable to configure alpha constraint: " + Arrays.toString(a), e); } } } NodeTestCase testCase = (NodeTestCase) context.get("TestCase"); List<String> classImports = new ArrayList<String>(); List<String> pkgImports = new ArrayList<String>(); for (String imp : testCase.getImports()) { if (imp.endsWith(".*")) { pkgImports.add(imp.substring(0, imp.lastIndexOf('.'))); } else { classImports.add(imp); } } // build an external function executor MVELCompilationUnit compilationUnit = new MVELCompilationUnit( name, expr, pkgImports.toArray(new String[0]), // pkg imports classImports.toArray(new String[0]), // imported classes new String[] {}, // imported methods new String[] {}, // imported fields new String[] {}, // global identifiers new Declaration[] {}, // previous declarations new Declaration[] {(Declaration) context.get(expr)}, // local declarations new String[] {}, // other identifiers new String[] {}, // input identifiers new String[] {}, // input types 4, false); AccumulateFunction accFunction = new SumAccumulateFunction(); Accumulator accumulator = new MVELAccumulatorFunctionExecutor(compilationUnit, accFunction); ((MVELCompileable) accumulator).compile(Thread.currentThread().getContextClassLoader()); Accumulate accumulate = new Accumulate( sourcePattern, new Declaration[] {}, // required declaration new Declaration[] {}, // inner declarations new Accumulator[] {accumulator}); AccumulateNode accNode = new AccumulateNode( buildContext.getNextId(), leftTupleSource, rightObjectSource, alphaResultConstraint, betaSourceConstraints, new EmptyBetaConstraints(), new Behavior[] {}, accumulate, false, buildContext); accNode.attach(); context.put(name, accNode); } else { StringBuilder msgBuilder = new StringBuilder(); msgBuilder.append("Can not parse AccumulateNode step arguments: \n"); for (String[] arg : args) { msgBuilder.append(" "); msgBuilder.append(Arrays.toString(arg)); msgBuilder.append("\n"); } throw new IllegalArgumentException(msgBuilder.toString()); } }
public static boolean isPropertyReactive(BuildContext context, Class<?> objectClass) { TypeDeclaration typeDeclaration = context.getRuleBase().getTypeDeclaration(objectClass); return typeDeclaration != null && typeDeclaration.isPropertyReactive(); }
@Test public void testUpdateSinkWithoutMemory() throws FactException, IntrospectionException { // An AlphaNode should try and repropagate from its source ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase(); 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.INSERTION, null, null, null); final MockObjectSource source = new MockObjectSource(buildContext.getNextId()); final InternalReadAccessor extractor = store.getReader(Cheese.class, "type", getClass().getClassLoader()); final FieldValue field = FieldFactory.getInstance().getFieldValue("cheddar"); final MvelConstraint constraint = new MvelConstraintTestUtil("type == \"cheddar\"", field, extractor); 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()); }
public void testQueryTerminalNode() { final ClassObjectType queryObjectType = new ClassObjectType(DroolsQuery.class); final ObjectTypeNode queryObjectTypeNode = new ObjectTypeNode(this.buildContext.getNextId(), queryObjectType, buildContext); queryObjectTypeNode.attach(); ClassFieldExtractor extractor = cache.getExtractor(DroolsQuery.class, "name", DroolsQuery.class.getClassLoader()); FieldValue field = FieldFactory.getFieldValue("query-1"); final Evaluator evaluator = ValueType.STRING_TYPE.getEvaluator(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(), 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 static ReteooStatefulSession readSession( ReteooStatefulSession session, DefaultAgenda agenda, long time, boolean multithread, MarshallerReaderContext context) throws IOException, ClassNotFoundException { if (session.getTimerService() instanceof PseudoClockScheduler) { PseudoClockScheduler clock = (PseudoClockScheduler) session.getTimerService(); clock.advanceTime(time, TimeUnit.MILLISECONDS); } // RuleFlowGroups need to reference the session for (RuleFlowGroup group : agenda.getRuleFlowGroupsMap().values()) { ((RuleFlowGroupImpl) group).setWorkingMemory(session); } context.wm = session; context.handles.put( context.wm.getInitialFactHandle().getId(), context.wm.getInitialFactHandle()); if (context.stream.readBoolean()) { InternalFactHandle initialFactHandle = context.wm.getInitialFactHandle(); int sinkId = context.stream.readInt(); ObjectTypeNode initialFactNode = (ObjectTypeNode) context.sinks.get(sinkId); if (initialFactNode == null) { // ------ START RANT ------ // The following code is as bad as it looks, but since I was so far // unable to convince Mark that creating OTNs on demand is really bad, // I have to continue doing it :) EntryPointNode defaultEPNode = context.ruleBase.getRete().getEntryPointNode(EntryPoint.DEFAULT); BuildContext buildContext = new BuildContext( context.ruleBase, context.ruleBase.getReteooBuilder().getIdGenerator()); buildContext.setPartitionId(RuleBasePartitionId.MAIN_PARTITION); buildContext.setObjectTypeNodeMemoryEnabled(true); initialFactNode = new ObjectTypeNode( sinkId, defaultEPNode, ClassObjectType.InitialFact_ObjectType, buildContext); // isn't contention something everybody loves? context.ruleBase.lock(); try { // Yeah, I know, because one session is being deserialized, we go and lock all of them... initialFactNode.attach(buildContext); } finally { context.ruleBase.unlock(); } // ------- END RANT ----- } ObjectHashSet initialFactMemory = (ObjectHashSet) context.wm.getNodeMemory(initialFactNode); initialFactMemory.add(initialFactHandle); readRightTuples(initialFactHandle, context); } while (context.readShort() == PersisterEnums.ENTRY_POINT) { String entryPointId = context.stream.readUTF(); WorkingMemoryEntryPoint wmep = context.wm.getEntryPoints().get(entryPointId); readFactHandles(context, ((NamedEntryPoint) wmep).getObjectStore()); } InternalFactHandle handle = context.wm.getInitialFactHandle(); while (context.stream.readShort() == PersisterEnums.LEFT_TUPLE) { LeftTupleSink sink = (LeftTupleSink) context.sinks.get(context.stream.readInt()); LeftTuple leftTuple = sink.createLeftTuple(handle, sink, true); readLeftTuple(leftTuple, context); } readPropagationContexts(context); readActivations(context); readActionQueue(context); readTruthMaintenanceSystem(context); if (processMarshaller != null) { processMarshaller.readProcessInstances(context); } else { short type = context.stream.readShort(); if (PersisterEnums.END != type) { throw new IllegalStateException( "No process marshaller, unable to unmarshall type: " + type); } } if (processMarshaller != null) { processMarshaller.readWorkItems(context); } else { short type = context.stream.readShort(); if (PersisterEnums.END != type) { throw new IllegalStateException( "No process marshaller, unable to unmarshall type: " + type); } } if (processMarshaller != null) { // This actually does ALL timers, due to backwards compatability issues // It will read in old JBPM binaries, but always write to the new binary format. processMarshaller.readProcessTimers(context); } else { short type = context.stream.readShort(); if (PersisterEnums.END != type) { throw new IllegalStateException( "No process marshaller, unable to unmarshall type: " + type); } } // no legacy jBPM timers, so handle locally while (context.readShort() == PersisterEnums.DEFAULT_TIMER) { InputMarshaller.readTimer(context); } if (multithread) { session.startPartitionManagers(); } return session; }