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]);
  }
  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 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());
  }