package edu.stanford.peer.rbtm.engine; import java.util.*; import edu.stanford.peer.rbtm.credential.*; import edu.stanford.peer.rbtm.util.*; /** * A credential graph node to represent an intersection. */ public class IntersectionProofNode extends AbstractProofNode { /** Initial capacity for a new intersection proof node */ private int CAPACITY = 10; /** * Backward solution monitor for this node. * @see IntersectionMonitor */ private IntersectionMonitor iMonitor; /** The number sub-part expressions which belong to this intersection */ private int k = 0; /** * Generic constructor for creating a new intersection proof node in a * credential graph. * @param g The credential graph to which the node should belong * @param i The intersection role expression the node represents * @param type The track type used for result evidence maps */ protected IntersectionProofNode(ProofGraph g, Intersection i, int type) { super(g, i, type); } public HashSet getChain(int size, EntityExpression target) { Iterator parts = ((Intersection)getRoleExp()).getParts(); ProofGraph graph = getGraph(); HashSet results = new HashSet(); if(getRoleExp().equals(target)) { return(new HashSet(size++)); } while(parts.hasNext()) { EntityExpression part = (EntityExpression)parts.next(); //System.out.println("&&&&& Getting chain from " + //part + " to " + target); results.addAll(graph.getChain(part, target)); } return results; } public void additionalBackwardProcess() { if (iMonitor != null)return; Intersection i = (Intersection)getRoleExp(); iMonitor = new IntersectionMonitor(); Iterator parts = i.getParts(); k = i.getPartsCount(); while(parts.hasNext()) { EntityExpression expr = (EntityExpression)parts.next(); ProofNode node = getGraph().addBackwardNode(expr); node.addBackwardListener(iMonitor); Debug.debugInfo(iMonitor.toString() + ": adding expr = " + expr ); } } /** * This method derives from RoleProofNode. */ public void additionalForwardProcess() { } /** * A listener for monitoring possible backward solutions. */ class IntersectionMonitor implements BackwardSolutionListener { /** * a partial solutions map */ HashMap results = new HashMap(CAPACITY); /** * Solutions are stored internally until all child nodes return a * specific solution at which time the solution is propagted to the * parent. * @param source child node which propagates the answer to its parent * @param soln an entity expression instance which is a partial sol'n */ public void backwardSolutionAdded(ProofNode source, BackwardSolution soln) { // list of sources for this soln SolutionCounter counter = (SolutionCounter)results.get(soln); // if this is a new solution then create a new list if(counter == null) { counter = new SolutionCounter(); // use k even if k grows results.put(soln, counter); // add new counter to table } counter.increment(); if(counter.isDone()) { // AbstractProofNode IntersectionProofNode.super.backwardSolutionAdded(source,soln); } else Debug.debugInfo(toString() + ": part soln " + soln + " = " + counter); } /** * Creates a human readable version of ther current intersection * instance. Expression parts are separated with the '^' operator. */ public String toString() { return "Monitor for (" + getRoleExp() + " w/k = " + k + ")"; } /** * A class to monitor the number of solution matches received * by an intersection's proof node. */ class SolutionCounter { /** * The counter integer */ private int count = 0; /** * Increment the counter by one. */ public void increment() { count += 1; } /** * A test method to see if the counter has max'ed out. * * @return true if count reaches k otherwise false. */ public boolean isDone() { return (count >= k && k != 0); } /** * To see what value the counter has set. */ public String toString() { return Integer.toString(count); } } } }