added GraphViz support
[sbp.git] / src / edu / berkeley / sbp / util / GraphViz.java
1 package edu.berkeley.sbp.util;
2 import edu.berkeley.sbp.util.*;
3 import edu.berkeley.sbp.*;
4 import java.io.*;
5 import java.util.*;
6 import java.lang.reflect.*;
7 import java.lang.ref.*;
8
9 public class GraphViz {
10
11     IdentityHashMap<ToGraphViz,Node> ihm = new IdentityHashMap<ToGraphViz,Node>();
12     HashMap<Node,Group> groups = new HashMap<Node,Group>();
13
14     public class Group {
15         public Group() { }
16         public void add(Node n) { groups.put(n, this); }
17     }
18
19     private static int master_idx=0;
20     public class Node {
21         private final int idx = master_idx++;
22         public String label;
23         public boolean directed = false;
24         public String color="black";
25         public ArrayList<Node> edges = new ArrayList<Node>();
26         public ArrayList<Node> inbound = new ArrayList<Node>();
27         public void edge(ToGraphViz o) {
28             Node n = o.toGraphViz(GraphViz.this);
29             if (n==null) return;
30             edges.add(n);
31             n.inbound.add(this);
32         }
33         public String name() {
34             if (inbound.size()==1 && inbound.get(0).simple())
35                 return inbound.get(0).name()+":node_"+idx;
36             return "node_"+idx;
37         }
38         public void edges(PrintWriter pw) {
39             if (simple()) return;
40             for(Node n : edges)
41                 pw.println("    "+name()+" -> " + n.name());
42         }
43         public int numEdges() { return edges.size(); }
44         public boolean simple() {
45             boolean simple = true;
46             if (label!=null && !label.equals("")) simple = false;
47             if (simple)
48                 for(Node n : edges)
49                     //if (n.numEdges()>0) { simple = false; break; }
50                     if (n.inbound.size() > 1) { simple = false; break; }
51             return simple;
52         }
53         public void dump(PrintWriter pw) {
54             if (inbound.size() > 0) {
55                 boolean good = false;
56                 for(Node n : inbound)
57                     if (!n.simple())
58                         { good = true; break; }
59                 if (!good) return;
60             }
61             pw.print("    "+name());
62             pw.print(" [");
63             if (directed) pw.print("ordering=out");
64             if (simple()) {
65                 pw.print(" shape=record ");
66                 pw.print(" label=\"{");
67                 boolean first = true;
68                 for(Node n : edges) {
69                     if (!first) pw.print("|");
70                     first = false;
71                     pw.print("<"+n.name()+">");
72                     pw.print(StringUtil.escapify(n.label,"\\\""));
73                 }
74                 pw.print("}\"");
75             } else {
76                 pw.print(" label=\"");
77                 pw.print(StringUtil.escapify(label,"\\\""));
78                 pw.print("\"");
79             }
80             pw.print("color="+color);
81             pw.print("];\n");
82         }
83     }
84
85     public boolean hasNode(ToGraphViz o) {
86         return ihm.get(o)!=null;
87     }
88
89     public Node createNode(ToGraphViz o) {
90         Node n = ihm.get(o);
91         if (n!=null) return n;
92         n = new Node();
93         ihm.put(o, n);
94         return n;
95     }
96
97     public static interface ToGraphViz {
98         public Node    toGraphViz(GraphViz gv);
99         public boolean isTransparent();
100         public boolean isHidden();
101     }
102
103     public void dump(PrintWriter pw) {
104         IdentityHashMap<Node,Node> done = new IdentityHashMap<Node,Node>();
105         pw.println("digraph G {\n");
106         for(Group g : groups.values()) {
107             pw.println("  { rank=same;\n");
108             for(Node n : groups.keySet())
109                 if (groups.get(n)==g) {
110                     done.put(n,n);
111                     n.dump(pw);
112                 }
113             pw.println("  }\n");
114         }
115         for(Node n : ihm.values()) {
116             if (done.get(n)!=null) continue;
117             n.dump(pw);
118         }
119         for(Node n : ihm.values()) n.edges(pw);
120         pw.println("}\n");
121     }
122
123 }