001: package org.drools.reteoo;
002:
003: /*
004: * Copyright 2005 JBoss Inc
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: import java.beans.IntrospectionException;
020:
021: import org.drools.Cheese;
022: import org.drools.DroolsTestCase;
023: import org.drools.FactException;
024: import org.drools.RuleBaseConfiguration;
025: import org.drools.RuleBaseFactory;
026: import org.drools.base.ClassFieldExtractor;
027: import org.drools.base.ClassFieldExtractorCache;
028: import org.drools.base.FieldFactory;
029: import org.drools.base.ValueType;
030: import org.drools.base.evaluators.Operator;
031: import org.drools.common.DefaultFactHandle;
032: import org.drools.common.PropagationContextImpl;
033: import org.drools.rule.LiteralConstraint;
034: import org.drools.rule.Rule;
035: import org.drools.spi.Evaluator;
036: import org.drools.spi.FieldExtractor;
037: import org.drools.spi.FieldValue;
038: import org.drools.spi.PropagationContext;
039: import org.drools.util.FactHashTable;
040:
041: public class AlphaNodeTest extends DroolsTestCase {
042:
043: public void testMemory() {
044: final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory(
045: 1, (ReteooRuleBase) RuleBaseFactory.newRuleBase());
046:
047: final AlphaNode alphaNode = new AlphaNode(2, null, null, true,
048: 3);
049:
050: final FactHashTable memory = (FactHashTable) workingMemory
051: .getNodeMemory(alphaNode);
052:
053: assertNotNull(memory);
054: }
055:
056: public void testLiteralConstraintAssertObjectWithMemory()
057: throws Exception {
058: final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory(
059: 1, (ReteooRuleBase) RuleBaseFactory.newRuleBase());
060: final Rule rule = new Rule("test-rule");
061: final PropagationContext context = new PropagationContextImpl(
062: 0, PropagationContext.ASSERTION, null, null);
063:
064: final MockObjectSource source = new MockObjectSource(15);
065:
066: final ClassFieldExtractor extractor = ClassFieldExtractorCache
067: .getExtractor(Cheese.class, "type", getClass()
068: .getClassLoader());
069:
070: final FieldValue field = FieldFactory.getFieldValue("cheddar");
071:
072: final Evaluator evaluator = ValueType.OBJECT_TYPE
073: .getEvaluator(Operator.EQUAL);
074: final LiteralConstraint constraint = new LiteralConstraint(
075: extractor, evaluator, field);
076:
077: // With Memory
078: final AlphaNode alphaNode = new AlphaNode(2, constraint,
079: source, true, 3); // has memory
080:
081: final MockObjectSink sink = new MockObjectSink();
082: alphaNode.addObjectSink(sink);
083:
084: final Cheese cheddar = new Cheese("cheddar", 5);
085: final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory
086: .insert(cheddar);
087:
088: // check sink is empty
089: assertLength(0, sink.getAsserted());
090:
091: // check alpha memory is empty
092: final FactHashTable memory = (FactHashTable) workingMemory
093: .getNodeMemory(alphaNode);
094:
095: assertEquals(0, memory.size());
096:
097: // object should assert as it passes text
098: alphaNode.assertObject(f0, context, workingMemory);
099:
100: assertEquals(1, sink.getAsserted().size());
101: assertEquals(1, memory.size());
102: Object[] list = (Object[]) sink.getAsserted().get(0);
103: assertSame(cheddar, workingMemory
104: .getObject((DefaultFactHandle) list[0]));
105: assertTrue("Should contain 'cheddar handle'", memory
106: .contains(f0));
107:
108: final Cheese stilton = new Cheese("stilton", 6);
109: final DefaultFactHandle f1 = new DefaultFactHandle(1, stilton);
110:
111: // object should NOT assert as it does not pass test
112: alphaNode.assertObject(f1, context, workingMemory);
113:
114: assertLength(1, sink.getAsserted());
115: assertEquals(1, memory.size());
116: list = (Object[]) sink.getAsserted().get(0);
117: assertSame(cheddar, workingMemory
118: .getObject((DefaultFactHandle) list[0]));
119: assertTrue("Should contain 'cheddar handle'", memory
120: .contains(f0));
121: }
122:
123: public void testLiteralConstraintAssertObjectWithoutMemory()
124: throws Exception {
125: final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory(
126: 1, (ReteooRuleBase) RuleBaseFactory.newRuleBase());
127: final Rule rule = new Rule("test-rule");
128: final PropagationContext context = new PropagationContextImpl(
129: 0, PropagationContext.ASSERTION, null, null);
130:
131: final MockObjectSource source = new MockObjectSource(15);
132:
133: final ClassFieldExtractor extractor = ClassFieldExtractorCache
134: .getExtractor(Cheese.class, "type", getClass()
135: .getClassLoader());
136:
137: final FieldValue field = FieldFactory.getFieldValue("cheddar");
138:
139: final Evaluator evaluator = ValueType.OBJECT_TYPE
140: .getEvaluator(Operator.EQUAL);
141: final LiteralConstraint constraint = new LiteralConstraint(
142: extractor, evaluator, field);
143:
144: // With Memory
145: final AlphaNode alphaNode = new AlphaNode(2, constraint,
146: source, false, 3); // no memory
147:
148: final MockObjectSink sink = new MockObjectSink();
149: alphaNode.addObjectSink(sink);
150:
151: final Cheese cheddar = new Cheese("cheddar", 5);
152: final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory
153: .insert(cheddar);
154:
155: // check sink is empty
156: assertLength(0, sink.getAsserted());
157:
158: // check alpha memory is empty
159: final FactHashTable memory = (FactHashTable) workingMemory
160: .getNodeMemory(alphaNode);
161:
162: assertEquals(0, memory.size());
163:
164: // object should assert as it passes text
165: alphaNode.assertObject(f0, context, workingMemory);
166:
167: assertEquals(1, sink.getAsserted().size());
168: assertEquals(0, memory.size());
169: Object[] list = (Object[]) sink.getAsserted().get(0);
170: assertSame(cheddar, workingMemory
171: .getObject((DefaultFactHandle) list[0]));
172: assertFalse("Should not contain 'cheddar handle'", memory
173: .contains(f0));
174:
175: final Cheese stilton = new Cheese("stilton", 6);
176: final DefaultFactHandle f1 = new DefaultFactHandle(1, stilton);
177:
178: // object should NOT assert as it does not pass test
179: alphaNode.assertObject(f1, context, workingMemory);
180:
181: assertLength(1, sink.getAsserted());
182: assertEquals(0, memory.size());
183: list = (Object[]) sink.getAsserted().get(0);
184: assertSame(cheddar, workingMemory
185: .getObject((DefaultFactHandle) list[0]));
186: assertFalse("Should not contain 'cheddar handle'", memory
187: .contains(f0));
188: }
189:
190: public void testLiteralConstraintAssertSequentialMode()
191: throws Exception {
192: RuleBaseConfiguration conf = new RuleBaseConfiguration();
193: conf.setSequential(true);
194: final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory(
195: 1, (ReteooRuleBase) RuleBaseFactory.newRuleBase(conf));
196: final Rule rule = new Rule("test-rule");
197: final PropagationContext context = new PropagationContextImpl(
198: 0, PropagationContext.ASSERTION, null, null);
199:
200: final MockObjectSource source = new MockObjectSource(15);
201:
202: final ClassFieldExtractor extractor = ClassFieldExtractorCache
203: .getExtractor(Cheese.class, "type", getClass()
204: .getClassLoader());
205:
206: final FieldValue field = FieldFactory.getFieldValue("cheddar");
207:
208: final Evaluator evaluator = ValueType.OBJECT_TYPE
209: .getEvaluator(Operator.EQUAL);
210: final LiteralConstraint constraint = new LiteralConstraint(
211: extractor, evaluator, field);
212:
213: // With Memory
214: final AlphaNode alphaNode = new AlphaNode(2, constraint,
215: source, true, 3); // has memory
216:
217: final MockObjectSink sink = new MockObjectSink();
218: alphaNode.addObjectSink(sink);
219:
220: final Cheese cheddar = new Cheese("cheddar", 5);
221: final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory
222: .insert(cheddar);
223:
224: // check sink is empty
225: assertLength(0, sink.getAsserted());
226:
227: // check alpha memory is empty
228: final FactHashTable memory = (FactHashTable) workingMemory
229: .getNodeMemory(alphaNode);
230:
231: assertEquals(0, memory.size());
232:
233: // object should assert as it passes text
234: alphaNode.assertObject(f0, context, workingMemory);
235:
236: assertEquals(1, sink.getAsserted().size());
237: assertEquals(0, memory.size());
238: Object[] list = (Object[]) sink.getAsserted().get(0);
239: assertSame(cheddar, workingMemory
240: .getObject((DefaultFactHandle) list[0]));
241:
242: final Cheese stilton = new Cheese("stilton", 6);
243: final DefaultFactHandle f1 = new DefaultFactHandle(1, stilton);
244:
245: // object should NOT assert as it does not pass test
246: alphaNode.assertObject(f1, context, workingMemory);
247:
248: assertLength(1, sink.getAsserted());
249: assertEquals(0, memory.size());
250: list = (Object[]) sink.getAsserted().get(0);
251: assertSame(cheddar, workingMemory
252: .getObject((DefaultFactHandle) list[0]));
253: }
254:
255: /*
256: * dont need to test with and without memory on this, as it was already done
257: * on the previous two tests. This just test AlphaNode With a different
258: * Constraint type.
259: */
260: public void testReturnValueConstraintAssertObject()
261: throws Exception {
262: final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory(
263: 1, (ReteooRuleBase) RuleBaseFactory.newRuleBase());
264: final Rule rule = new Rule("test-rule");
265: final PropagationContext context = new PropagationContextImpl(
266: 0, PropagationContext.ASSERTION, null, null);
267:
268: final MockObjectSource source = new MockObjectSource(15);
269:
270: final FieldExtractor extractor = ClassFieldExtractorCache
271: .getExtractor(Cheese.class, "type", getClass()
272: .getClassLoader());
273:
274: final FieldValue field = FieldFactory.getFieldValue("cheddar");
275:
276: final Evaluator evaluator = ValueType.OBJECT_TYPE
277: .getEvaluator(Operator.EQUAL);
278: final LiteralConstraint constraint = new LiteralConstraint(
279: extractor, evaluator, field);
280:
281: final AlphaNode alphaNode = new AlphaNode(2, constraint,
282: source, true, 3);
283: final MockObjectSink sink = new MockObjectSink();
284: alphaNode.addObjectSink(sink);
285:
286: final Cheese cheddar = new Cheese("cheddar", 5);
287:
288: final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory
289: .insert(cheddar);
290:
291: assertLength(0, sink.getAsserted());
292:
293: // object should assert as it passes text
294: alphaNode.assertObject(f0, context, workingMemory);
295:
296: assertLength(1, sink.getAsserted());
297: final Object[] list = (Object[]) sink.getAsserted().get(0);
298: assertSame(cheddar, workingMemory
299: .getObject((DefaultFactHandle) list[0]));
300:
301: final Cheese stilton = new Cheese("stilton", 6);
302: f0.setObject(stilton);
303:
304: sink.getAsserted().clear();
305:
306: // object should not assert as it does not pass text
307: alphaNode.assertObject(f0, context, workingMemory);
308:
309: assertLength(0, sink.getAsserted());
310: }
311:
312: public void testRetractObjectWithMemory() throws Exception {
313: final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory(
314: 1, (ReteooRuleBase) RuleBaseFactory.newRuleBase());
315: final Rule rule = new Rule("test-rule");
316: final PropagationContext context = new PropagationContextImpl(
317: 0, PropagationContext.ASSERTION, null, null);
318:
319: final MockObjectSource source = new MockObjectSource(15);
320:
321: final FieldExtractor extractor = ClassFieldExtractorCache
322: .getExtractor(Cheese.class, "type", getClass()
323: .getClassLoader());
324:
325: final FieldValue field = FieldFactory.getFieldValue("cheddar");
326:
327: final Evaluator evaluator = ValueType.OBJECT_TYPE
328: .getEvaluator(Operator.EQUAL);
329: final LiteralConstraint constraint = new LiteralConstraint(
330: extractor, evaluator, field);
331:
332: final AlphaNode alphaNode = new AlphaNode(2, constraint,
333: source, true, 3); // has memory
334: final MockObjectSink sink = new MockObjectSink();
335: alphaNode.addObjectSink(sink);
336:
337: final Cheese cheddar = new Cheese("cheddar", 5);
338:
339: final DefaultFactHandle f0 = new DefaultFactHandle(0, cheddar);
340:
341: // check alpha memory is empty
342: final FactHashTable memory = (FactHashTable) workingMemory
343: .getNodeMemory(alphaNode);
344: assertEquals(0, memory.size());
345:
346: // object should assert as it passes text
347: alphaNode.assertObject(f0, context, workingMemory);
348:
349: assertEquals(1, memory.size());
350:
351: final DefaultFactHandle f1 = new DefaultFactHandle(1, "cheese");
352:
353: // object should NOT retract as it doesn't exist
354: alphaNode.retractObject(f1, context, workingMemory);
355:
356: assertLength(0, sink.getRetracted());
357: assertEquals(1, memory.size());
358: assertTrue("Should contain 'cheddar handle'", memory
359: .contains(f0));
360:
361: // object should retract as it does exist
362: alphaNode.retractObject(f0, context, workingMemory);
363:
364: assertLength(1, sink.getRetracted());
365: assertEquals(0, memory.size());
366: final Object[] list = (Object[]) sink.getRetracted().get(0);
367: assertSame(f0, list[0]);
368:
369: }
370:
371: public void testRetractObjectWithoutMemory() throws Exception {
372: final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory(
373: 1, (ReteooRuleBase) RuleBaseFactory.newRuleBase());
374: final Rule rule = new Rule("test-rule");
375: final PropagationContext context = new PropagationContextImpl(
376: 0, PropagationContext.ASSERTION, null, null);
377:
378: final MockObjectSource source = new MockObjectSource(15);
379:
380: final FieldExtractor extractor = ClassFieldExtractorCache
381: .getExtractor(Cheese.class, "type", getClass()
382: .getClassLoader());
383:
384: final FieldValue field = FieldFactory.getFieldValue("cheddar");
385:
386: final Evaluator evaluator = ValueType.OBJECT_TYPE
387: .getEvaluator(Operator.EQUAL);
388: final LiteralConstraint constraint = new LiteralConstraint(
389: extractor, evaluator, field);
390:
391: final AlphaNode alphaNode = new AlphaNode(2, constraint,
392: source, false, 3); // no memory
393: final MockObjectSink sink = new MockObjectSink();
394: alphaNode.addObjectSink(sink);
395:
396: final Cheese cheddar = new Cheese("cheddar", 5);
397:
398: final DefaultFactHandle f0 = new DefaultFactHandle(0, cheddar);
399:
400: // check alpha memory is empty
401: final FactHashTable memory = (FactHashTable) workingMemory
402: .getNodeMemory(alphaNode);
403: assertEquals(0, memory.size());
404:
405: // object should assert as it passes text
406: alphaNode.assertObject(f0, context, workingMemory);
407:
408: assertEquals(0, memory.size());
409:
410: final DefaultFactHandle f1 = new DefaultFactHandle(1,
411: new Cheese("brie", 10));
412:
413: // object should NOT retract as it doesn't exist
414: alphaNode.retractObject(f1, context, workingMemory);
415:
416: // without memory, it will always propagate a retract
417: assertLength(0, sink.getRetracted());
418: assertEquals(0, memory.size());
419: assertFalse("Should not contain 'cheddar handle'", memory
420: .contains(f0));
421:
422: // object should retract as it does exist
423: alphaNode.retractObject(f0, context, workingMemory);
424:
425: assertLength(1, sink.getRetracted());
426: assertEquals(0, memory.size());
427: final Object[] list = (Object[]) sink.getRetracted().get(0);
428: assertSame(f0, list[0]);
429:
430: }
431:
432: public void testUpdateSinkWithMemory() throws FactException,
433: IntrospectionException {
434: // An AlphaNode with memory should not try and repropagate from its source
435: // Also it should only update the latest tuple sinky
436:
437: final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory(
438: 1, (ReteooRuleBase) RuleBaseFactory.newRuleBase());
439: final Rule rule = new Rule("test-rule");
440: final PropagationContext context = new PropagationContextImpl(
441: 0, PropagationContext.ASSERTION, null, null);
442:
443: final MockObjectSource source = new MockObjectSource(1);
444:
445: final FieldExtractor extractor = ClassFieldExtractorCache
446: .getExtractor(Cheese.class, "type", getClass()
447: .getClassLoader());
448:
449: final FieldValue field = FieldFactory.getFieldValue("cheddar");
450:
451: final Evaluator evaluator = ValueType.OBJECT_TYPE
452: .getEvaluator(Operator.EQUAL);
453: final LiteralConstraint constraint = new LiteralConstraint(
454: extractor, evaluator, field);
455:
456: final AlphaNode alphaNode = new AlphaNode(2, constraint,
457: source, true, 3); // has memory
458:
459: alphaNode.attach();
460:
461: final MockObjectSink sink1 = new MockObjectSink();
462: alphaNode.addObjectSink(sink1);
463:
464: // Assert a single fact which should be in the AlphaNode memory and also
465: // propagated to the
466: // the tuple sink
467: final Cheese cheese = new Cheese("cheddar", 0);
468: final DefaultFactHandle handle1 = new DefaultFactHandle(1,
469: cheese);
470:
471: alphaNode.assertObject(handle1, context, workingMemory);
472:
473: assertLength(1, sink1.getAsserted());
474:
475: // Attach a new tuple sink
476: final MockObjectSink sink2 = new MockObjectSink();
477:
478: // Tell the alphanode to update the new node. Make sure the first sink1
479: // is not updated
480: // likewise the source should not do anything
481: alphaNode.updateSink(sink2, context, workingMemory);
482:
483: assertLength(1, sink1.getAsserted());
484: assertLength(1, sink2.getAsserted());
485: assertEquals(0, source.getUdated());
486: }
487:
488: public void testUpdateSinkWithoutMemory() throws FactException,
489: IntrospectionException {
490: // An AlphaNode without memory should try and repropagate from its source
491: final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory(
492: 1, (ReteooRuleBase) RuleBaseFactory.newRuleBase());
493: final Rule rule = new Rule("test-rule");
494: final PropagationContext context = new PropagationContextImpl(
495: 0, PropagationContext.ASSERTION, null, null);
496:
497: final MockObjectSource source = new MockObjectSource(1);
498:
499: final FieldExtractor extractor = ClassFieldExtractorCache
500: .getExtractor(Cheese.class, "type", getClass()
501: .getClassLoader());
502:
503: final FieldValue field = FieldFactory.getFieldValue("cheddar");
504:
505: final Evaluator evaluator = ValueType.OBJECT_TYPE
506: .getEvaluator(Operator.EQUAL);
507: final LiteralConstraint constraint = new LiteralConstraint(
508: extractor, evaluator, field);
509:
510: final AlphaNode alphaNode = new AlphaNode(2, constraint,
511: source, false, 3); // no memory
512:
513: alphaNode.attach();
514:
515: final MockObjectSink sink1 = new MockObjectSink();
516: alphaNode.addObjectSink(sink1);
517:
518: // Assert a single fact which should be in the AlphaNode memory and also
519: // propagated to the
520: // the tuple sink
521: final Cheese cheese = new Cheese("cheddar", 0);
522: final DefaultFactHandle handle1 = new DefaultFactHandle(1,
523: cheese);
524: // adding handle to the mock source
525: source.addFact(handle1);
526:
527: alphaNode.assertObject(handle1, context, workingMemory);
528:
529: assertLength(1, sink1.getAsserted());
530:
531: // Attach a new tuple sink
532: final MockObjectSink sink2 = new MockObjectSink();
533:
534: // Tell the alphanode to update the new node. Make sure the first sink1
535: // is not updated
536: // likewise the source should not do anything
537: alphaNode.updateSink(sink2, context, workingMemory);
538:
539: assertLength(1, sink1.getAsserted());
540: assertLength(1, sink2.getAsserted());
541: assertEquals(1, source.getUdated());
542: }
543:
544: }
|