Index: fedd/abac-src/ttg/process/TTG.java
===================================================================
--- fedd/abac-src/ttg/process/TTG.java	(revision 8780cbecc6db2bdc2b9ef31eec6e5209ad3bff15)
+++ fedd/abac-src/ttg/process/TTG.java	(revision 8780cbecc6db2bdc2b9ef31eec6e5209ad3bff15)
@@ -0,0 +1,421 @@
+package com.nailabs.abac.process;
+
+import com.nailabs.abac.trust.*;
+import com.nailabs.abac.test.*;
+import com.nailabs.abac.credential.*;
+import edu.stanford.peer.rbtm.credential.*;
+import edu.stanford.peer.rbtm.engine.*;
+
+import edu.stanford.rt.credential.CredentialDomain;
+import edu.stanford.rt.credential.CredentialStore;
+import edu.stanford.rt.credential.RTContext;
+import edu.stanford.rt.parser.RTParser;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.*;
+
+/**
+ * A trust target graph (TTG) is used to represent the state of a trust
+ * negotiation in process (one per graph). 
+ * @version	$Id: TTG.java,v 1.50 2003/02/26 00:45:11 jjacobs Exp $	
+
+ */
+public class TTG extends Observable implements Observer { 
+    /** The top-level trust target the system is trying to solve. */
+    protected TargetNode root;
+
+    /** An index of TTGNodes based on their trust targets */
+    protected Hashtable indexByTT = new Hashtable();
+
+    /** The old change list for this graph */
+    protected Message oldDelta =  new Message();
+
+    /** The current change list for this graph */
+    protected Message newDelta = new Message();
+
+    /** A set of all previoussent credentials */
+    protected HashSet outCache = new HashSet();
+
+    /** A graph engine for storing remotely held credential */
+    protected GraphEngine oppoCreds = null;
+
+    /** An RTML parser for de-serializing RTML evidence */
+    protected RTParser parser = null;
+    
+    /** An RTML context for incoming opponent's credentials */
+    protected RTContext rtc = null;
+
+    /** A context for a single trust negotiation */
+    protected NegotiationContext context;
+
+    /** Create a trust target graph for a specific negotiation */
+    public TTG(NegotiationContext context){
+	this.context = context;
+	if(context.getFrontier() instanceof RtmlFrontier) {
+	    try {
+		parser = new RTParser();
+		rtc = new RTContext(parser);
+		oppoCreds = new RtmlEngine(new CredentialStore(parser));
+	    }
+	    catch(Exception ex) {
+		debug("rtml", ex.getMessage());
+	    }
+	} else {
+	    oppoCreds = new GraphEngine();
+	}
+    }
+
+    /** Propagates node state change information to a graph observer */
+    public void update(Observable o, Object arg) {
+	//if(o instanceof TTGNode) {
+	setChanged();
+	notifyObservers(arg);
+	//}
+	//else {
+	//debug("update", "received unexpected observation from " + arg);
+	//}
+    }
+
+    /**
+     * This returns an internal list of all node in the trust target graph.
+     * WARNING: this should be a privileged function for production use. Also,
+     * any changes to the TTG will invalidate this iterator!
+     */
+    public Iterator getNodes() {
+        return indexByTT.values().iterator();
+    }
+
+    public TTGNode getNode(Goal key) {
+	TTGNode node = getNodeByHash(key);
+	if(node == null) {
+	    node = TTGNode.createNode(key);
+	    putNodeByHash(node);
+	    debug("node", "initialized node for " + key);
+	}
+	else {
+	    debug("node", "found node for " + key);
+
+	}
+	return node;
+    }
+
+    /** Access a trust target node by the goal it represents */
+    public TTGNode getNodeByHash(Goal key) {
+	return (TTGNode)indexByTT.get(key.toString());
+    }
+
+    /** Entry point for global or local changes. */
+    public void putNodeByHash(TTGNode node) {
+	indexByTT.put(node.getGoal().toString(), node);
+	debug("node", "putting " + node.getGoal());
+	node.init(context);
+	context.getStrategy().addToWorklist(node);
+	context.getStrategy().addNewNode(node);
+	setChanged();
+	notifyObservers((Object)node);
+    
+    }
+
+    public void putRoot(TargetNode node) {
+	debug("root", "putting root" + node);
+	root = node;
+	setChanged();
+	notifyObservers((Object)node);
+    }
+
+    /** A method to reset the change list at the end of a processing cycle */
+    public void reset() { 
+        //consolidate credentials 
+        Iterator i = newDelta.getEvidence();
+        while(i.hasNext()) {
+            Object potential = i.next();
+            if(outCache.contains(potential)) {
+                i.remove();
+            } else {
+                outCache.add(potential);
+            }
+        }
+        oldDelta = newDelta;    // swap out the deltas 
+        newDelta = new Message();     
+        setChanged();           // notify observers of the changed message
+        notifyObservers((Object)oldDelta);
+    }
+
+    /** Accessor method for the change list on the graph and resets the list */
+    public Message getChanges() {
+	return newDelta;
+    }
+    
+    public boolean verifyEvidence(Operation op) {
+        Entity self = context.getSelf();
+        if(op instanceof LinkingImplicationEdge) {
+            return false;
+        }
+        if((op instanceof ImplicationEdge)) { 
+            Goal g = ((EdgeOperation)op).getParent();
+            debug("message", "verifying operation " + op);
+            return(self.equals(g.getVerifier()));
+        }
+        debug("message", "not verifying operation " + op);
+        return false;
+    }
+
+    /** boolean query to determine whether the sepcified goal needs evidence */
+    public boolean provideEvidence(Operation edge) {
+        Goal g = ((EdgeOperation)edge).getParent();
+        Entity self = context.getSelf();
+        return (!self.equals(g.getVerifier()));
+    }
+
+    /** Update this graph with changes contained in the specified message */
+    public void update(Message msg) throws Exception {
+	setChanged();
+	//notifyObservers("<Update location=\"remote\">\n");
+	notifyObservers("location = remote");
+	Iterator ev = msg.getEvidence();
+	while(ev.hasNext()) {
+	    Object eObj = ev.next();
+	    if(eObj instanceof String) {
+		String xml = (String) eObj;
+		InputStream in = new ByteArrayInputStream(xml.getBytes());
+		CredentialDomain domain = 
+		    parser.parseCredentialDomain(in, rtc);
+		((RtmlEngine)oppoCreds).addDomain(domain);
+		debug("message", "received evidence = " + domain);
+	    }
+	    else {
+		StaticCredential credential = (StaticCredential)eObj;
+		Debug.rbtmStart();
+		oppoCreds.addCredential(credential);        
+		Debug.rbtmStop();
+		debug("message", "received evidence = " + credential);
+	    }
+	}
+	Iterator operations = msg.getOperations();
+	while(operations.hasNext()) {
+	    Operation op = (Operation)operations.next();
+	    debug("message", "performing op " + op);
+	    if(verifyEvidence(op)) {
+		EdgeOperation edgeOp = (EdgeOperation)op;
+		TrustTarget parent = (TrustTarget)edgeOp.getParent();
+		TrustTarget child = (TrustTarget)edgeOp.getChild();
+		HashSet evidence = null;
+		
+		//try {
+                EntityExpression parentRole = parent.getTargetRole();
+                EntityExpression childRole = child.getTargetRole();
+                debug("message", "chain search from " + 
+                      parentRole + " to " + childRole);
+                Debug.rbtmStart();                
+                oppoCreds.backwardSearch(parentRole);
+                if(parentRole.equals(childRole)) {
+                    debug("message", "roles are equal bailing out now!");
+                } else {
+                    evidence = oppoCreds.getChain(parentRole, childRole);
+                    // }
+		    Debug.rbtmStop();
+		    //} catch(Exception ex) {
+		    //ex.printStackTrace();
+		    //throw(new java.rmi.RemoteException("Unjustified implication!!"));
+		}
+		edgeOp.setEvidence(evidence);
+		debug("message", "evidence = " + evidence);
+	    }
+	    setChanged();
+	    notifyObservers((Object)op);
+	    op.perform(this);
+	} 
+	setChanged();
+	//notifyObservers("</Update>\n");
+    }
+
+
+    /** 
+     * Accessor method for of root of graph. This is necessary to traverse
+     * the graph. 
+     * @returns the root node which may be any TTGNode descendent.
+     */
+    public TargetNode getRoot() {
+	return root;
+    }
+
+
+    // Methods in this section are recorded in the delta list
+
+    /** 
+     * Insert a new root node for this graph. 
+     * <I>This is a global operation</I>
+     */
+    public void setRoot(TrustTarget target) {
+	debug("root", "setting root = " + target);
+	NodeOperation op = new NodeOperation
+	    (target, target.getInitialProcessingState(context), true);
+	setChanged();
+	notifyObservers(op);
+	op.perform(this);
+	newDelta.addOperation(op);
+    }
+    
+    /**
+     * Mark a node in the graph as opponent processed.
+     */
+    public void setOpponentProcessed(Goal id) {
+	//TTGNode node = getNode(id);
+	//ProcessingState state = node.getProcessingState();
+	//state.opponentProcess(state);
+	setNode(id, new ProcessingState(false, true));
+    }
+
+    /**
+     * Mark a node in the graph as verifier processed.
+     */
+    public void setVerifierProcessed(Goal id) {
+	//TTGNode node = getNode(id);
+	//ProcessingState state = node.getProcessingState();
+	//state.verifierProcess();
+	setNode(id, new ProcessingState(true, false));
+    }
+
+
+    /**
+     * Add a root or modify a node to this TTG and replicate the changes on 
+     * the opponent's TTG.
+     * <I>This is a global operation</I>
+     */
+    public void setNode(Goal id, ProcessingState state)
+    {
+        ProcessingState copy = new ProcessingState();
+        copy.update(state);
+        NodeOperation nodeOp = new NodeOperation(id, copy); 
+        context.getStrategy().scheduleOperation(nodeOp);
+    }
+
+    /** actually performs the node operation on this graph */
+    public void performNode(NodeOperation nodeOp) {
+        // This is slightly different than perform edge although they
+        // could possibly be merged into a single performOperation method
+        nodeOp.perform(this);
+        newDelta.addOperation((Operation)nodeOp);
+        setChanged();
+        notifyObservers((Object)nodeOp);
+    }
+
+    /** actually performs a previously scheduled edge operation */
+    public void performEdge(EdgeOperation edgeOp) 
+    {
+        if(edgeOp instanceof LinkingImplicationEdge) {
+            setChanged();
+            notifyObservers("location = async");
+        }
+        setChanged();
+        notifyObservers((Object)edgeOp);
+        edgeOp.perform(this);
+        if(edgeOp instanceof ImplicationEdge && provideEvidence(edgeOp)) {
+            debug("message", " %%%% adding evidence for " + edgeOp.toString());
+            newDelta.addOperation((Operation)edgeOp);
+        } else {
+            debug("message", " %%%% not adding evidence for" + 
+                  edgeOp.toString());
+            newDelta.addOperationWithoutEvidence((Operation)edgeOp);
+        }
+        if(edgeOp instanceof LinkingImplicationEdge) {
+            setChanged();
+            notifyObservers("location = sync");
+        }
+    }
+
+    /**
+     * Add a new control edge to this TTG and replicate the changes on the 
+     * opponent's TTG.
+     * <I>This is a global operation</I>
+     */
+    public void addControlEdge(Goal parent, Goal child)
+    {
+        TTGNode cnode = getNodeByHash(child);
+        ProcessingState state =  (cnode == null)? 
+            child.getInitialProcessingState(context): null;
+        EdgeOperation edgeOp = new ControlEdge(parent, child, state);
+        context.getStrategy().scheduleOperation(edgeOp);
+    }
+
+    /**
+     * Add a new implication edge to this TTG and replicate the changes on the 
+     * opponent's TTG.
+     * <I>This is a global operation</I>
+     */
+    public void addImplicationEdge(Goal parent, Goal child, HashSet creds) {
+        TTGNode cnode = getNodeByHash(child);
+        //debug("node", "implication cnode = " + cnode); 
+        ProcessingState state = (cnode == null)? 
+            child.getInitialProcessingState(context): null;
+        ImplicationEdge edgeOp = 
+            new ImplicationEdge(parent, child,  state, creds);
+        context.getStrategy().scheduleOperation(edgeOp);
+    }
+
+    /**
+     * Add a new intersection edge to this TTG and replicate the edge on the
+     * opponent's TTG. <i>This is a global operation</i>
+     */
+    public void addIntersectionEdge(TrustTarget parent, TrustTarget child) {
+        TargetNode cnode = (TargetNode)getNodeByHash(child);
+        debug("node", "implication cnode = " + cnode); 
+        ProcessingState state = (cnode == null)? 
+            child.getInitialProcessingState(context): null;
+        IntersectionEdge edgeOp = new IntersectionEdge(parent, child,  state);
+        context.getStrategy().scheduleOperation(edgeOp);        
+    }
+
+    public void addLinkingMonitorEdge(TrustTarget parent, LinkingGoal child) {
+        TTGNode cnode = getNodeByHash(child);
+        ProcessingState state =  (cnode == null)? 
+            child.getInitialProcessingState(context): null;
+        EdgeOperation edgeOp = new LinkingMonitorEdge(parent, child, state);
+        context.getStrategy().scheduleOperation(edgeOp);
+    }
+
+    public void addLinkingSolutionEdge(LinkingGoal monitor, TrustTarget soln) {
+        TTGNode cnode = getNodeByHash(soln);
+        ProcessingState state =  (cnode == null)? 
+            soln.getInitialProcessingState(context): null;
+        EdgeOperation edgeOp = new LinkingSolutionEdge(monitor, soln, state);
+        context.getStrategy().scheduleOperation(edgeOp);
+    }
+
+    public void addLinkingImplicationEdge(TrustTarget parent, TrustTarget child)
+    {
+        TTGNode cnode = getNodeByHash(child);
+        ProcessingState state =  (cnode == null)? 
+            child.getInitialProcessingState(context): null;
+        EdgeOperation edgeOp = 
+            new LinkingImplicationEdge(parent, child, state);
+        context.getStrategy().scheduleOperation(edgeOp);
+    }
+
+    /** Friendly debugging convenience method */
+    protected void debug(String level, String message) {
+	StringBuffer buff = new StringBuffer("TTG[");
+	buff.append(context.getSelf()).append("]: ").append(message);
+	Debug.debug(level, buff.toString());
+    }
+
+
+    public String toString() {
+	StringBuffer buff = new StringBuffer("[TTG EntityID=");
+	buff.append(context.getSelf().toString()).append("\n");
+	Iterator i = indexByTT.keySet().iterator();
+	while(i.hasNext()) {
+	    buff.append("\t").append(i.next()).append("\n");
+	}
+	buff.append("]");
+	return buff.toString();
+    }
+
+}
+
+
+
+
+
+
+
