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]); }
@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])); }
protected void initInferredMask(LeftTupleSource leftInput) { LeftTupleSource unwrappedLeft = unwrapLeftInput(leftInput); if (unwrappedLeft.getType() == NodeTypeEnums.LeftInputAdapterNode && ((LeftInputAdapterNode) unwrappedLeft).getParentObjectSource().getType() == NodeTypeEnums.AlphaNode) { AlphaNode alphaNode = (AlphaNode) ((LeftInputAdapterNode) unwrappedLeft).getParentObjectSource(); leftInferredMask = alphaNode.updateMask(leftDeclaredMask); } else { leftInferredMask = leftDeclaredMask; } leftInferredMask = leftInferredMask.resetAll(leftNegativeMask); }
@Override protected void initInferredMask(LeftTupleSource leftInput) { super.initInferredMask(leftInput); ObjectSource unwrappedRight = unwrapRightInput(); if (unwrappedRight instanceof AlphaNode) { AlphaNode alphaNode = (AlphaNode) unwrappedRight; rightInferredMask = alphaNode.updateMask(rightDeclaredMask); } else { rightInferredMask = rightDeclaredMask; } rightInferredMask &= (Long.MAX_VALUE - rightNegativeMask); }
/* * 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()); }
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); }
public void byPassModifyToBetaNode( final InternalFactHandle factHandle, final ModifyPreviousTuples modifyPreviousTuples, final PropagationContext context, final InternalWorkingMemory workingMemory) { final Object object = factHandle.getObject(); // We need to iterate in the same order as the assert if (this.hashedFieldIndexes != null) { // Iterate the FieldIndexes to see if any are hashed for (FieldIndex fieldIndex = this.hashedFieldIndexes.getFirst(); fieldIndex != null; 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 AlphaNode sink = (AlphaNode) this.hashedSinkMap.get(new HashKey(fieldIndex, object)); if (sink != null) { // only alpha nodes are hashable sink.getObjectSinkPropagator() .byPassModifyToBetaNode(factHandle, modifyPreviousTuples, context, workingMemory); } } } // propagate unhashed if (this.hashableSinks != null) { for (ObjectSinkNode sink = this.hashableSinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode()) { // only alpha nodes are hashable ((AlphaNode) sink) .getObjectSinkPropagator() .byPassModifyToBetaNode(factHandle, modifyPreviousTuples, context, workingMemory); } } if (this.otherSinks != null) { // propagate others for (ObjectSinkNode sink = this.otherSinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode()) { // compound alpha, lianode or betanode sink.byPassModifyToBetaNode(factHandle, modifyPreviousTuples, context, workingMemory); } } }
public void propagateModifyObject( final InternalFactHandle factHandle, final ModifyPreviousTuples modifyPreviousTuples, final PropagationContext context, final InternalWorkingMemory workingMemory) { final Object object = factHandle.getObject(); // Iterates the FieldIndex collection, which tells you if particularly field is hashed or not // 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 = this.hashedFieldIndexes.getFirst(); fieldIndex != null; 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 AlphaNode sink = (AlphaNode) this.hashedSinkMap.get(new HashKey(fieldIndex, object)); if (sink != null) { // go straight to the AlphaNode's propagator, as we know it's true and no need to retest sink.getObjectSinkPropagator() .propagateModifyObject(factHandle, modifyPreviousTuples, context, workingMemory); } } } // propagate unhashed if (this.hashableSinks != null) { for (ObjectSinkNode sink = this.hashableSinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode()) { doPropagateModifyObject(factHandle, modifyPreviousTuples, context, workingMemory, sink); } } if (this.otherSinks != null) { // propagate others for (ObjectSinkNode sink = this.otherSinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode()) { doPropagateModifyObject(factHandle, modifyPreviousTuples, context, workingMemory, sink); } } }
public ObjectSinkPropagator removeObjectSink(final ObjectSink sink) { this.sinks = null; // dirty it, so it'll rebuild on next get if (sink.getType() == NodeTypeEnums.AlphaNode) { final AlphaNode alphaNode = (AlphaNode) sink; final AlphaNodeFieldConstraint fieldConstraint = alphaNode.getConstraint(); if (fieldConstraint instanceof IndexableConstraint) { final IndexableConstraint indexableConstraint = (IndexableConstraint) fieldConstraint; final FieldValue value = indexableConstraint.getField(); if (isHashable(indexableConstraint)) { final InternalReadAccessor fieldAccessor = indexableConstraint.getFieldExtractor(); final int index = fieldAccessor.getIndex(); final FieldIndex fieldIndex = unregisterFieldIndex(index); if (fieldIndex.isHashed()) { HashKey hashKey = new HashKey(index, value, fieldAccessor); this.hashedSinkMap.remove(hashKey); if (fieldIndex.getCount() <= this.alphaNodeHashingThreshold - 1) { // we have less than three so unhash unHashSinks(fieldIndex); } } else { this.hashableSinks.remove(alphaNode); } if (this.hashableSinks != null && this.hashableSinks.isEmpty()) { this.hashableSinks = null; } return size() == 1 ? new SingleObjectSinkAdapter(getSinks()[0]) : this; } } } this.otherSinks.remove((ObjectSinkNode) sink); if (this.otherSinks.isEmpty()) { this.otherSinks = null; } return size() == 1 ? new SingleObjectSinkAdapter(getSinks()[0]) : this; }
static InternalReadAccessor getHashableAccessor(AlphaNode alphaNode) { AlphaNodeFieldConstraint fieldConstraint = alphaNode.getConstraint(); if (fieldConstraint instanceof IndexableConstraint) { IndexableConstraint indexableConstraint = (IndexableConstraint) fieldConstraint; if (isHashable(indexableConstraint)) { return indexableConstraint.getFieldExtractor(); } } return null; }
public ObjectSinkPropagator addObjectSink(ObjectSink sink, int alphaNodeHashingThreshold) { this.sinks = null; // dirty it, so it'll rebuild on next get if (sink.getType() == NodeTypeEnums.AlphaNode) { final AlphaNode alphaNode = (AlphaNode) sink; final InternalReadAccessor readAccessor = getHashableAccessor(alphaNode); if (readAccessor != null) { final int index = readAccessor.getIndex(); final FieldIndex fieldIndex = registerFieldIndex(index, readAccessor); // DROOLS-678 : prevent null values from being hashed as 0s final FieldValue value = ((IndexableConstraint) alphaNode.getConstraint()).getField(); if (fieldIndex.getCount() >= this.alphaNodeHashingThreshold && this.alphaNodeHashingThreshold != 0 && !value.isNull()) { if (!fieldIndex.isHashed()) { hashSinks(fieldIndex); } // no need to check, we know the sink does not exist this.hashedSinkMap.put( new HashKey(index, value, fieldIndex.getFieldExtractor()), alphaNode, false); } else { if (this.hashableSinks == null) { this.hashableSinks = new ObjectSinkNodeList(); } this.hashableSinks.add(alphaNode); } return this; } } if (this.otherSinks == null) { this.otherSinks = new ObjectSinkNodeList(); } this.otherSinks.add((ObjectSinkNode) sink); return this; }
void unHashSinks(final FieldIndex fieldIndex) { final int index = fieldIndex.getIndex(); // this is the list of sinks that need to be removed from the hashedSinkMap final List<HashKey> unhashedSinks = new ArrayList<HashKey>(); final Iterator iter = this.hashedSinkMap.newIterator(); ObjectHashMap.ObjectEntry entry = (ObjectHashMap.ObjectEntry) iter.next(); while (entry != null) { final AlphaNode alphaNode = (AlphaNode) entry.getValue(); final IndexableConstraint indexableConstraint = (IndexableConstraint) alphaNode.getConstraint(); // only alpha nodes that have an Operator.EQUAL are in sinks, so only check if it is // the right field index if (index == indexableConstraint.getFieldExtractor().getIndex()) { final FieldValue value = indexableConstraint.getField(); if (this.hashableSinks == null) { this.hashableSinks = new ObjectSinkNodeList(); } this.hashableSinks.add(alphaNode); unhashedSinks.add(new HashKey(index, value, fieldIndex.getFieldExtractor())); } entry = (ObjectHashMap.ObjectEntry) iter.next(); } for (HashKey hashKey : unhashedSinks) { this.hashedSinkMap.remove(hashKey); } if (this.hashedSinkMap.isEmpty()) { this.hashedSinkMap = null; } fieldIndex.setHashed(false); }
void hashSinks(final FieldIndex fieldIndex) { if (this.hashedSinkMap == null) { this.hashedSinkMap = new ObjectHashMap(); } final int index = fieldIndex.getIndex(); final InternalReadAccessor fieldReader = fieldIndex.getFieldExtractor(); ObjectSinkNode currentSink = this.hashableSinks.getFirst(); while (currentSink != null) { final AlphaNode alphaNode = (AlphaNode) currentSink; final AlphaNodeFieldConstraint fieldConstraint = alphaNode.getConstraint(); final IndexableConstraint indexableConstraint = (IndexableConstraint) fieldConstraint; // position to the next sink now because alphaNode may be removed if the index is equal. If we // were to do this // afterwards, currentSink.nextNode would be null currentSink = currentSink.getNextObjectSinkNode(); // only alpha nodes that have an Operator.EQUAL are in hashableSinks, so only check if it is // the right field index if (index == indexableConstraint.getFieldExtractor().getIndex()) { final FieldValue value = indexableConstraint.getField(); this.hashedSinkMap.put(new HashKey(index, value, fieldReader), alphaNode); // remove the alpha from the possible candidates of hashable sinks since it is now hashed hashableSinks.remove(alphaNode); } } if (this.hashableSinks.isEmpty()) { this.hashableSinks = null; } fieldIndex.setHashed(true); }
@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()); }
@Test public void testQueryTerminalNode() { final ClassObjectType queryObjectType = new ClassObjectType(DroolsQuery.class); final ObjectTypeNode queryObjectTypeNode = new ObjectTypeNode( this.buildContext.getNextId(), this.entryPoint, queryObjectType, buildContext); queryObjectTypeNode.attach(buildContext); ClassFieldReader extractor = store.getReader(DroolsQuery.class, "name"); MvelConstraint constraint = new MvelConstraintTestUtil( "name == \"query-1\"", FieldFactory.getInstance().getFieldValue("query-1"), extractor); final QueryImpl query = new QueryImpl("query-1"); buildContext.setRule(query); AlphaNode alphaNode = new AlphaNode(this.buildContext.getNextId(), constraint, queryObjectTypeNode, buildContext); alphaNode.attach(buildContext); final LeftInputAdapterNode liaNode = new LeftInputAdapterNode(this.buildContext.getNextId(), alphaNode, this.buildContext); liaNode.attach(buildContext); final ClassObjectType cheeseObjectType = new ClassObjectType(Cheese.class); final ObjectTypeNode cheeseObjectTypeNode = new ObjectTypeNode( this.buildContext.getNextId(), this.entryPoint, cheeseObjectType, buildContext); cheeseObjectTypeNode.attach(buildContext); extractor = store.getReader(Cheese.class, "type"); constraint = new MvelConstraintTestUtil( "type == \"stilton\"", FieldFactory.getInstance().getFieldValue("stilton"), extractor); alphaNode = new AlphaNode( this.buildContext.getNextId(), constraint, cheeseObjectTypeNode, buildContext); alphaNode.attach(buildContext); BuildContext buildContext = new BuildContext(kBase, kBase.getReteooBuilder().getIdGenerator()); buildContext.setTupleMemoryEnabled(false); final JoinNode joinNode = new JoinNode( this.buildContext.getNextId(), liaNode, alphaNode, EmptyBetaConstraints.getInstance(), buildContext); joinNode.attach(buildContext); final QueryTerminalNode queryNode = new QueryTerminalNode( this.buildContext.getNextId(), joinNode, query, ((QueryImpl) query).getLhs(), 0, buildContext); queryNode.attach(buildContext); final KnowledgePackageImpl pkg = new KnowledgePackageImpl("com.drools.test"); pkg.addRule(query); ((KnowledgeBaseImpl) kBase).addPackages(Arrays.asList(new InternalKnowledgePackage[] {pkg})); KieSession kSession = kBase.newKieSession(); QueryResults results = kSession.getQueryResults("query-1"); assertEquals(0, results.size()); final Cheese stilton1 = new Cheese("stilton", 100); final FactHandle handle1 = kSession.insert(stilton1); results = kSession.getQueryResults("query-1"); assertEquals(1, results.size()); final Cheese cheddar = new Cheese("cheddar", 55); kSession.insert(cheddar); results = kSession.getQueryResults("query-1"); assertEquals(1, results.size()); final Cheese stilton2 = new Cheese("stilton", 5); final FactHandle handle2 = kSession.insert(stilton2); results = kSession.getQueryResults("query-1"); assertEquals(2, results.size()); /** * QueryResultsRow result = results.get( 0 ); assertEquals( 1, result.size() ); assertEquals( * stilton1, result.get( 0 ) ); * * <p>result = results.get( 1 ); assertEquals( 1, result.size() ); assertEquals( stilton2, * result.get( 0 ) ); */ int i = 0; for (final Iterator<QueryResultsRow> it = results.iterator(); it.hasNext(); ) { QueryResultsRow resultRow = it.next(); if (i == 1) { // assertSame( stilton2, result.g( 0 ) ); } else { // assertSame( stilton1, result.get( 0 ) ); } i++; } kSession.delete(handle1); results = kSession.getQueryResults("query-1"); assertEquals(1, results.size()); kSession.delete(handle2); results = kSession.getQueryResults("query-1"); assertEquals(0, results.size()); }
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()); }