ef08fae8ab8a028d443b84bb9f056e248141396b
[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 String comment;
24         public boolean directed = false;
25         public String color="black";
26         public ArrayList<Node> edges = new ArrayList<Node>();
27         public ArrayList<Object> labels = new ArrayList<Object>();
28         public ArrayList<Node> inbound = new ArrayList<Node>();
29         public void edge(ToGraphViz o, Object label) {
30             Node n = o.toGraphViz(GraphViz.this);
31             if (n==null) return;
32             edges.add(n);
33             labels.add(label);
34             n.inbound.add(this);
35         }
36         public String name() {
37             if (inbound.size()==1 && inbound.get(0).simple())
38                 return inbound.get(0).name()+":node_"+idx;
39             return "node_"+idx;
40         }
41         public void edges(PrintWriter pw) {
42             if (simple()) return;
43             for(int i=0; i<edges.size(); i++) {
44                 Node n = edges.get(i);
45                 Object label = labels.get(i);
46                 pw.println("    "+name()+" -> " + n.name() + " [color="+color+" " +(label==null?"":("label=\""+label+"\""))+ "];\n");
47             }
48         }
49         public int numEdges() { return edges.size(); }
50         public boolean simple() {
51             boolean simple = true;
52             if (label!=null && !label.equals("")) simple = false;
53             if (simple)
54                 for(Node n : edges)
55                     //if (n.numEdges()>0) { simple = false; break; }
56                     if (n.inbound.size() > 1) { simple = false; break; }
57             return simple;
58         }
59         public void dump(PrintWriter pw) {
60             if (inbound.size() > 0) {
61                 boolean good = false;
62                 for(Node n : inbound)
63                     if (!n.simple())
64                         { good = true; break; }
65                 if (!good) return;
66             }
67             pw.print("    "+name());
68             pw.print(" [");
69             if (directed) pw.print("ordering=out");
70             if (simple()) {
71                 pw.print(" shape=record ");
72                 pw.print(" label=\"");
73                 boolean complex = false;
74                 for(Node n : edges)
75                     if (n.edges.size()>0)
76                         complex = true;
77                 if (!complex) pw.print("{");
78                 boolean first = true;
79                 for(Node n : edges) {
80                     if (!first) pw.print("|");
81                     first = false;
82                     pw.print("<node_"+n.idx+">");
83                     pw.print(StringUtil.escapify(n.label,"\\\""));
84                 }
85                 if (!complex) pw.print("}");
86                 pw.print("\"");
87             } else {
88                 pw.print(" label=\"");
89                 pw.print(StringUtil.escapify(label,"\\\""));
90                 pw.print("\"");
91             }
92             pw.print("color="+color);
93             if (comment!=null) pw.print(" comment=\""+StringUtil.escapify(comment,"\\\"")+"\" ");
94             pw.print("];\n");
95         }
96     }
97
98     public boolean hasNode(ToGraphViz o) {
99         return ihm.get(o)!=null;
100     }
101
102     public Node createNode(ToGraphViz o) {
103         Node n = ihm.get(o);
104         if (n!=null) return n;
105         n = new Node();
106         ihm.put(o, n);
107         return n;
108     }
109
110     public static interface ToGraphViz {
111         public Node    toGraphViz(GraphViz gv);
112         public boolean isTransparent();
113         public boolean isHidden();
114     }
115
116     public void show() throws IOException {
117         Runtime.getRuntime().exec(new String[] { "dot", "-Tsvg" });
118     }
119
120     public void dump(PrintWriter pw) {
121         IdentityHashMap<Node,Node> done = new IdentityHashMap<Node,Node>();
122         pw.println("digraph G { rankdir=LR; ordering=out; \n");
123         for(Group g : groups.values()) {
124             pw.println("  { rank=same;\n");
125             for(Node n : groups.keySet())
126                 if (groups.get(n)==g) {
127                     done.put(n,n);
128                     n.dump(pw);
129                 }
130             pw.println("  }\n");
131         }
132         for(Node n : ihm.values()) {
133             if (done.get(n)!=null) continue;
134             n.dump(pw);
135         }
136         for(Node n : ihm.values()) n.edges(pw);
137         pw.println("}\n");
138         pw.flush();
139     }
140
141 }