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 extends Node {
15         private final int idx = master_idx++;
16         public boolean cluster = false;
17         public boolean primary = true;
18         public Group() { }
19         public void add(Node n) { groups.put(n, this); }
20         public String name() { return cluster?("cluster_"+idx):("subgraph_"+idx); }
21         public boolean simple() { return false; }
22         public void dump(PrintWriter pw, IdentityHashMap<Node,Node> done) {
23             Group g = this;
24             if (done.get(g)!=null) return;
25             done.put(g,g);
26             pw.println("  subgraph "+name()+" { rank=same;\n");
27             pw.println("  label=\""+StringUtil.escapify(label.toString(), "\\\"\r\n")+"\";\n");
28             pw.println("  color="+g.color+";\n");
29             pw.println("  shape="+g.shape+";\n");
30             for(Node n : groups.keySet())
31                 if (groups.get(n)==g)
32                     n.dump(pw, done);
33             pw.println("  }\n");
34         }
35     }
36
37     private static int master_idx=0;
38
39     public class Node {
40         private final int idx = master_idx++;
41         public String label;
42         public String comment;
43         public boolean directed = false;
44         public String color="black";
45         public String fill="white";
46         public String shape="ellipse";
47         public ArrayList<Node> edges = new ArrayList<Node>();
48         public ArrayList<Object> labels = new ArrayList<Object>();
49         public ArrayList<Node> inbound = new ArrayList<Node>();
50         public void edge(ToGraphViz o, Object label) {
51             Node n = o.toGraphViz(GraphViz.this);
52             if (n==null) return;
53             edges.add(n);
54             labels.add(label);
55             n.inbound.add(this);
56         }
57         public String getParentName() {
58             if (inbound.size()==1 && inbound.get(0).simple())
59                 return inbound.get(0).getParentName();
60             return name();
61         }
62         public String name() {
63             if (inbound.size()==1 && inbound.get(0).simple())
64                 return inbound.get(0).getParentName()+":node_"+idx;
65             return "node_"+idx;
66         }
67         public void edges(PrintWriter pw) {
68             if (simple()) return;
69             for(int i=0; i<edges.size(); i++) {
70                 Node n = edges.get(i);
71                 Object label = labels.get(i);
72                 pw.println("    "+name()+" -> " + n.name() + " [color="+color+" "
73                            +(label==null?"":("label=\""+StringUtil.escapify(label.toString(), "\\\"\r\n")+"\""))+ "];\n");
74             }
75         }
76         public int numEdges() { return edges.size(); }
77         public boolean simple() {
78             boolean simple = true;
79             if (label!=null && !label.equals("")) simple = false;
80             if (simple)
81                 for(Node n : edges)
82                     //if (n.numEdges()>0) { simple = false; break; }
83                     if (n.inbound.size() > 1) { simple = false; break; }
84             return simple;
85         }
86         public void dump(PrintWriter pw, IdentityHashMap<Node,Node> done) {
87             if (done.get(this)!=null) return;
88             done.put(this, this);
89             if (inbound.size() > 0) {
90                 boolean good = false;
91                 for(Node n : inbound)
92                     if (!n.simple())
93                         { good = true; break; }
94                 if (!good) return;
95             }
96             pw.print("    "+name());
97             pw.print(" [");
98             if (directed) pw.print("ordering=out");
99             if (simple()) {
100                 pw.print(" shape=record ");
101                 pw.print(" label=\"");
102                 boolean complex = false;
103                 for(Node n : edges)
104                     if (n.edges.size()>0)
105                         complex = true;
106                 if (!complex) pw.print("{");
107                 boolean first = true;
108                 for(Node n : edges) {
109                     if (!first) pw.print("|");
110                     first = false;
111                     pw.print("<node_"+n.idx+">");
112                     pw.print(StringUtil.escapify(n.label,"\\\"\r\n"));
113                 }
114                 if (!complex) pw.print("}");
115                 pw.print("\" ");
116             } else {
117                 pw.print(" label=\"");
118                 pw.print(StringUtil.escapify(label,"\\\"\r\n"));
119                 pw.print("\" ");
120             }
121             pw.print("color="+color);
122             if (comment!=null) pw.print(" comment=\""+StringUtil.escapify(comment,"\\\"\r\n")+"\" ");
123             pw.print("];\n");
124         }
125     }
126
127     public boolean hasNode(ToGraphViz o) {
128         return ihm.get(o)!=null;
129     }
130
131     public Node createNode(ToGraphViz o) {
132         Node n = ihm.get(o);
133         if (n!=null) return n;
134         n = new Node();
135         ihm.put(o, n);
136         return n;
137     }
138
139     public Group createGroup(ToGraphViz o) {
140         Group n = (Group)ihm.get(o);
141         if (n!=null) return n;
142         n = new Group();
143         ihm.put(o, n);
144         return n;
145     }
146
147     public static interface ToGraphViz {
148         Node    toGraphViz(GraphViz gv);
149         boolean isTransparent();
150         boolean isHidden();
151     }
152
153     public void show() throws IOException {
154         Runtime.getRuntime().exec(new String[] { "dot", "-Tsvg" });
155     }
156
157     public void dump(OutputStream os) { dump(new PrintWriter(new OutputStreamWriter(os))); }
158     public void dump(PrintWriter pw) {
159         IdentityHashMap<Node,Node> done = new IdentityHashMap<Node,Node>();
160         pw.println("digraph G { rankdir=LR; ordering=out; compound=true; \n");
161         for(Group g : groups.values())
162             if (g.primary)
163                 g.dump(pw, done);
164         for(Node n : ihm.values()) {
165             if (done.get(n)!=null) continue;
166             if (n instanceof Group) continue;
167             n.dump(pw, done);
168         }
169         for(Node n : ihm.values()) n.edges(pw);
170         pw.println("}\n");
171         pw.flush();
172     }
173
174 }