package jadex.rules.rulesystem.rete.nodes; import jadex.rules.rulesystem.AbstractAgenda; import jadex.rules.rulesystem.rete.Tuple; import jadex.rules.rulesystem.rete.constraints.ConstraintIndexer; import jadex.rules.rulesystem.rete.constraints.IConstraintEvaluator; import jadex.rules.state.IOAVState; import jadex.rules.state.OAVAttributeType; import java.util.Collection; import java.util.Iterator; /** * A beta node has the purpose to perform a constraints check * between (at least) two objects. The beta node has to incoming * coming connections which both can activate the node. */ public class BetaNode extends AbstractBetaNode { //-------- constructors -------- /** * Create a new beta node. */ public BetaNode(int nodeid, IConstraintEvaluator[] evaluators, ConstraintIndexer[] xevaluators) { super(nodeid, evaluators, xevaluators); } //-------- tuple consumer interface (left) -------- /** * Modify a tuple in this node. * @param left The tuple. */ public void modifyTuple(Tuple left, int tupleindex, OAVAttributeType type, Object oldvalue, Object newvalue, IOAVState state, ReteMemory mem, AbstractAgenda agenda) { if(!getRelevantAttributes().contains(type)) return; super.modifyTuple(left, tupleindex, type, oldvalue, newvalue, state, mem, agenda); if(!isAffected(type)) { Collection omem = fetchObjectMemory(state, left, mem); if(omem!=null) { for(Iterator it=omem.iterator(); it.hasNext(); ) { Object right = it.next(); boolean contains = isMatchContained(state, left, right, mem); // Tuple changed in memory -> propagate modification if(contains) propagateModification(left, right, tupleindex, type, oldvalue, newvalue, state, mem, agenda); } } } } //-------- object consumer interface (right) -------- /** * Propagate an object change to this node. * @param right The new object. */ public void modifyObject(Object right, OAVAttributeType type, Object oldvalue, Object newvalue, IOAVState state, ReteMemory mem, AbstractAgenda agenda) { if(!getRelevantAttributes().contains(type)) return; super.modifyObject(right, type, oldvalue, newvalue, state, mem, agenda); if(!isAffected(type)) { Collection tmem = fetchTupleMemory(state, right, mem); if(tmem!=null) { for(Iterator it=tmem.iterator(); it.hasNext(); ) { Tuple left = (Tuple)it.next(); boolean contains = isMatchContained(state, left, right, mem); // Tuple changed in memory -> propagate modification if(contains) propagateModification(left, right, left.size(), type, oldvalue, newvalue, state, mem, agenda); } } } } //-------- template methods -------- /** * Add a match to the node memory and propagate if necessary. */ protected void addMatch(Tuple left, Object right, IOAVState state, ReteMemory mem, AbstractAgenda agenda) { Tuple result = mem.getTuple(state, left, right); BetaMemory bmem = (BetaMemory)mem.getNodeMemory(this); if(bmem.addResultTuple(result)) { ITupleConsumerNode[] tcs = tconsumers; for(int j=0; tcs!=null && j<tcs.length; j++) tcs[j].addTuple(result, state, mem, agenda); } } /** * Remove a match from the node memory and propagate if necessary. */ protected void removeMatch(Tuple left, Object right, IOAVState state, ReteMemory mem, AbstractAgenda agenda) { if(mem.hasNodeMemory(this)) { Tuple result = mem.getTuple(state, left, right); if(((BetaMemory)mem.getNodeMemory(this)).removeResultTuple(result)) { // if(getNodeId()==3713) // System.out.println("remmi: "+result); ITupleConsumerNode[] tcs = tconsumers; for(int j=0; tcs!=null && j<tcs.length; j++) tcs[j].removeTuple(result, state, mem, agenda); } } } /** * Propagate a change of a tuple in the result memory. */ protected void propagateModification(Tuple left, Object right, int tupleindex, OAVAttributeType type, Object oldvalue, Object newvalue, IOAVState state, ReteMemory mem, AbstractAgenda agenda) { Tuple tuple = mem.getTuple(state, left, right); ITupleConsumerNode[] tcs = tconsumers; for(int j=0; tcs!=null && j<tcs.length; j++) tcs[j].modifyTuple(tuple, tupleindex, type, oldvalue, newvalue, state, mem, agenda); } /** * Check if a match is contained. */ protected boolean isMatchContained(IOAVState state, Tuple left, Object right, ReteMemory mem) { return mem.hasNodeMemory(this) && ((BetaMemory)mem.getNodeMemory(this)).getResultMemory() .contains(mem.getTuple(state, left, right)); } /** * Check the consistency of the node. */ public boolean checkNodeConsistency(ReteMemory mem) { boolean consistent = true; Collection tuples = getNodeMemory(mem); Collection objects = getObjectSource().getNodeMemory(mem); if(tuples!=null) { for(Iterator it=tuples.iterator(); consistent && it.hasNext(); ) { Tuple tuple = (Tuple)it.next(); consistent = objects.contains(tuple.getObject()); } } Object node = this; while(node instanceof IObjectConsumerNode) node = ((IObjectConsumerNode)node).getObjectSource(); ((ReteNode)node).checked.add(this); return consistent; } }