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