Index: java/GraphTest.java
===================================================================
--- java/GraphTest.java	(revision a2a15557df0cdbfd71ff854eaab2067b5186cce8)
+++ java/GraphTest.java	(revision de63a317080c88276a1a13c98506018efeac86c5)
@@ -22,26 +22,4 @@
  */
 public class GraphTest {
-    /**
-     * Translate either keys to nicknames or vice versa.  Break the string into
-     * space separated tokens and then each of them into period separated
-     * strings.  If any of the smallest strings is in the map, replace it with
-     * the value.
-     */
-    protected static String replace(String is, Map<String, String> m) {
-	String rv = "";
-	for (String tok: is.split(" ")) {
-	    String term = "";
-	    for (String s: tok.split("\\.")) {
-		String next = m.containsKey(s) ? m.get(s) : s;
-
-		if (term.isEmpty()) term = next;
-		else term += "." + next;
-	    }
-	    if (rv.isEmpty()) rv = term;
-	    else rv += " " + term;
-	}
-	return rv;
-    }
-
 
     /**
@@ -60,6 +38,5 @@
      * the credential graph then any alias files into the two maps.
      */
-    protected static void importDir(File d, CredentialGraph g, 
-	    Map<String, String> nick, Map<String, String> keys) {
+    protected static void importDir(File d, CredentialGraph g) {
 	Vector<File> ids = new Vector<File>();
 	Vector<File> creds = new Vector<File>();
@@ -75,6 +52,4 @@
 
 		Credential.addIdentity(id);
-		nick.put(id.getName(), id.getKeyID());
-		keys.put(id.getKeyID(),id.getName());
 	    }
 	    catch (Exception e) {
@@ -102,6 +77,4 @@
 	TreeMap<String, String> nicknames = new TreeMap<String, String>();
 	TreeMap<String, String> keys = new TreeMap<String, String>();
-        String role = args[args.length-2];
-        String prin = args[args.length-1];
 
 	for (int i= 0; i < args.length-2; i++) {
@@ -110,10 +83,8 @@
 	    try {
 		if (f.isDirectory()) 
-		    importDir(f, graph, nicknames, keys);
+		    importDir(f, graph);
 		else if (f.getPath().endsWith(".pem")) {
 		    Identity id = new Identity(f);
 		    Credential.addIdentity(id);
-		    nicknames.put(id.getName(), id.getKeyID());
-		    keys.put(id.getKeyID(),id.getName());
 		}
 		else if (f.getPath().endsWith(".der"))
@@ -127,18 +98,17 @@
 	}
 
-	// Translate nicknames into key ids.
-	role = replace(role, nicknames);
-	prin = replace(prin, nicknames);
         //
         // run the query
         //
 
+	Role role = new Role(args[args.length-2], true);
+	Role prin = new Role(args[args.length-1], true);
         Query q = graph.querier();
-        Graph<Role, Credential> ret = q.run(role, prin);
+        Graph<Role, Credential> ret = q.run(role.toString(), prin.toString());
 	String fn = "attr";
 	int n = 0;
 	String suf = ".der";
         for (Credential c : ret.getEdges()) {
-            System.out.println(replace(c.toString(), keys));
+            System.out.println(c.simpleString());
 	    c.write(fn + n++ + suf);
 	}
Index: java/net/deterlab/abac/Credential.java
===================================================================
--- java/net/deterlab/abac/Credential.java	(revision a2a15557df0cdbfd71ff854eaab2067b5186cce8)
+++ java/net/deterlab/abac/Credential.java	(revision de63a317080c88276a1a13c98506018efeac86c5)
@@ -140,4 +140,8 @@
     }
 
+    public String simpleString() {
+	return m_head.simpleString() + " <- " + m_tail.simpleString();
+    }
+
     public void write(OutputStream s) throws IOException {
 	s.write(m_ac.getEncoded());
@@ -148,5 +152,4 @@
     }
 
-
     private Role m_head, m_tail;
 
@@ -154,5 +157,9 @@
     private Identity m_id;
 
-    public static void addIdentity(Identity id) { s_ids.add(id); }
+    public static void addIdentity(Identity id) { 
+	s_ids.add(id);
+	if (id.getName() != null && id.getKeyID() != null) 
+	    Role.add_mapping(id.getName(), id.getKeyID());
+    }
     public static Collection<Identity> identities() { return s_ids; }
 }
Index: java/net/deterlab/abac/CredentialGraph.java
===================================================================
--- java/net/deterlab/abac/CredentialGraph.java	(revision a2a15557df0cdbfd71ff854eaab2067b5186cce8)
+++ java/net/deterlab/abac/CredentialGraph.java	(revision de63a317080c88276a1a13c98506018efeac86c5)
@@ -24,5 +24,7 @@
     public CredentialGraph() {
         /* create the graph */
-        g = Graphs.<Role,Credential>synchronizedDirectedGraph(new DirectedSparseGraph<Role,Credential>());
+        g = Graphs.<Role,Credential>synchronizedForest(
+		new DelegateForest(
+		    new DirectedSparseGraph<Role,Credential>()));
         pq = new Query(g);
     }
Index: java/net/deterlab/abac/Role.java
===================================================================
--- java/net/deterlab/abac/Role.java	(revision a2a15557df0cdbfd71ff854eaab2067b5186cce8)
+++ java/net/deterlab/abac/Role.java	(revision de63a317080c88276a1a13c98506018efeac86c5)
@@ -1,3 +1,5 @@
 package net.deterlab.abac;
+
+import java.util.*;
 
 /**
@@ -10,4 +12,9 @@
     private String m_prefix;
     private Role[] m_prereqs;
+
+    protected static TreeMap<String, String> nicknames = 
+	new TreeMap<String, String>();
+    protected static TreeMap<String, String> keys = 
+	new TreeMap<String, String>();
 
     /**
@@ -40,4 +47,8 @@
             m_parts = new String[0];
         }
+    }
+
+    public Role(String s, boolean translate) {
+	this(translate ? replace(s, nicknames) : s);
     }
 
@@ -139,4 +150,8 @@
     }
 
+    public String simpleString() {
+	return replace(m_string, keys);
+    }
+
     public boolean equals(Object v2) {
         if (v2 instanceof Role)
@@ -148,3 +163,30 @@
         return m_string.hashCode();
     }
+
+    /**
+     * Translate either keys to nicknames or vice versa.  Break the string into
+     * space separated tokens and then each of them into period separated
+     * strings.  If any of the smallest strings is in the map, replace it with
+     * the value.
+     */
+    protected static String replace(String is, Map<String, String> m) {
+	String rv = "";
+	for (String tok: is.split(" ")) {
+	    String term = "";
+	    for (String s: tok.split("\\.")) {
+		String next = m.containsKey(s) ? m.get(s) : s;
+
+		if (term.isEmpty()) term = next;
+		else term += "." + next;
+	    }
+	    if (rv.isEmpty()) rv = term;
+	    else rv += " " + term;
+	}
+	return rv;
+    }
+    public static void add_mapping(String name, String key) {
+	nicknames.put(name, key);
+	keys.put(key,name);
+    }
+
 }
