public void testActivationGroup() {
final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
final DefaultAgenda agenda = (DefaultAgenda) workingMemory.getAgenda();
final List list = new ArrayList();
// create the consequence
final Consequence consequence = new Consequence() {
private static final long serialVersionUID = 510l;
public void evaluate(KnowledgeHelper knowledgeHelper,
WorkingMemory workingMemory) {
list.add( knowledgeHelper.getRule() );
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
}
public void writeExternal(ObjectOutput out) throws IOException {
}
public String getName() {
return "default";
}
};
final LeftTupleImpl tuple = new LeftTupleImpl( new DefaultFactHandle( 1,
"cheese" ),
null,
true );
// create a rule for each agendaGroup
final Rule rule0 = new Rule( "test-rule0" );
rule0.setActivationGroup( "activation-group-0" );
final RuleTerminalNode node0 = new RuleTerminalNode( 3,
new MockTupleSource( 2 ),
rule0,
rule0.getLhs(),
0,
buildContext );
rule0.setConsequence( consequence );
final PropagationContext context0 = new PropagationContextImpl( 0,
PropagationContext.ASSERTION,
rule0,
null,
null );
final Rule rule1 = new Rule( "test-rule1" );
rule1.setActivationGroup( "activation-group-0" );
final RuleTerminalNode node1 = new RuleTerminalNode( 5,
new MockTupleSource( 4 ),
rule1,
rule1.getLhs(),
0,
buildContext );
rule1.setConsequence( consequence );
final PropagationContext context1 = new PropagationContextImpl( 0,
PropagationContext.ASSERTION,
rule1,
null,
null );
final Rule rule2 = new Rule( "test-rule2" );
rule2.setSalience( new SalienceInteger( -5 ) );
final RuleTerminalNode node2 = new RuleTerminalNode( 7,
new MockTupleSource( 6 ),
rule2,
rule2.getLhs(),
0,
buildContext );
rule2.setConsequence( consequence );
final PropagationContext context2 = new PropagationContextImpl( 0,
PropagationContext.ASSERTION,
rule2,
null,
null );
final Rule rule3 = new Rule( "test-rule3",
"agendaGroup3" );
rule3.setSalience( new SalienceInteger( -10 ) );
rule3.setActivationGroup( "activation-group-3" );
final RuleTerminalNode node3 = new RuleTerminalNode( 9,
new MockTupleSource( 8 ),
rule3,
rule3.getLhs(),
0,
buildContext );
rule3.setConsequence( consequence );
final PropagationContext context3 = new PropagationContextImpl( 0,
PropagationContext.ASSERTION,
rule3,
null,
null );
// Assert the tuple and check it was added to activation-group-0
node0.assertLeftTuple( tuple,
context0,
workingMemory );
agenda.unstageActivations();
final ActivationGroup activationGroup0 = agenda.getActivationGroup( "activation-group-0" );
assertEquals( 1,
activationGroup0.size() );
// Removing a tuple should remove the activation from the activation-group-0 again
node0.retractLeftTuple( tuple,
context0,
workingMemory );
assertEquals( 0,
activationGroup0.size() );
// Assert the tuple again and check it was added to activation-group-0
node0.assertLeftTuple( tuple,
context0,
workingMemory );
agenda.unstageActivations();
assertEquals( 1,
activationGroup0.size() );
// Assert another tuple and check it was added to activation-group-0
node1.assertLeftTuple( tuple,
context1,
workingMemory );
agenda.unstageActivations();
assertEquals( 2,
activationGroup0.size() );
// There should now be two potential activations to fire
assertEquals( 2,
agenda.focusStackSize() );
// The first tuple should fire, adding itself to the List and clearing and cancelling the other Activations in the activation-group-0
agenda.fireNextItem( null );
// Make sure the activation-group-0 is clear
assertEquals( 0,
activationGroup0.size() );
// Make sure the Agenda is empty
assertEquals( 0,
agenda.focusStackSize() );
// List should only have a single item, "rule0"
assertEquals( 1,
list.size() );
assertSame( rule1,
list.get( 0 ) );
list.clear();
//-------------------
// Now try a more complex scenario involving two Xor Groups and one rule not in a Group
node0.assertLeftTuple( tuple,
context0,
workingMemory );
node1.assertLeftTuple( tuple,
context1,
workingMemory );
node2.assertLeftTuple( tuple,
context2,
workingMemory );
node3.assertLeftTuple( tuple,
context3,
workingMemory );
agenda.unstageActivations();
// activation-group-0 should be populated again
assertEquals( 2,
activationGroup0.size() );
// make sure the activation-group-3 is cleared when we can clear the Agenda Group for the activation that is in both
final ActivationGroup activationGroup3 = agenda.getActivationGroup( "activation-group-3" );
assertEquals( 4,
agenda.agendaSize() );
assertEquals( 1,
activationGroup3.size() );
agenda.clearAndCancelAgendaGroup( "agendaGroup3" );
assertEquals( 3,
agenda.agendaSize() );
assertEquals( 0,
activationGroup3.size() );
// Activation for activation-group-0 should be next - the activation in no activation/agenda group should remain on the agenda
agenda.fireNextItem( null );
assertEquals( 1,
agenda.agendaSize() );
assertEquals( 0,
activationGroup0.size() );
// Fire the last activation and make sure the Agenda Empties
agenda.fireNextItem( null );
assertEquals( 0,
agenda.agendaSize() );
assertEquals( 2,
list.size() );
assertEquals( rule1,
list.get( 0 ) );