13899bb2540b108404b4774eebd4dc9f0a57bd5b
[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() + " [color="+color+"];\n");
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 complex = false;
68                 for(Node n : edges)
69                     if (n.edges.size()>0)
70                         complex = true;
71                 if (!complex) pw.print("{");
72                 boolean first = true;
73                 for(Node n : edges) {
74                     if (!first) pw.print("|");
75                     first = false;
76                     pw.print("<node_"+n.idx+">");
77                     pw.print(StringUtil.escapify(n.label,"\\\""));
78                 }
79                 if (!complex) pw.print("}");
80                 pw.print("\"");
81             } else {
82                 pw.print(" label=\"");
83                 pw.print(StringUtil.escapify(label,"\\\""));
84                 pw.print("\"");
85             }
86             pw.print("color="+color);
87             pw.print("];\n");
88         }
89     }
90
91     public boolean hasNode(ToGraphViz o) {
92         return ihm.get(o)!=null;
93     }
94
95     public Node createNode(ToGraphViz o) {
96         Node n = ihm.get(o);
97         if (n!=null) return n;
98         n = new Node();
99         ihm.put(o, n);
100         return n;
101     }
102
103     public static interface ToGraphViz {
104         public Node    toGraphViz(GraphViz gv);
105         public boolean isTransparent();
106         public boolean isHidden();
107     }
108
109     public void dump(PrintWriter pw) {
110         IdentityHashMap<Node,Node> done = new IdentityHashMap<Node,Node>();
111         pw.println("digraph G { rankdir=LR; \n");
112         for(Group g : groups.values()) {
113             pw.println("  { rank=same;\n");
114             for(Node n : groups.keySet())
115                 if (groups.get(n)==g) {
116                     done.put(n,n);
117                     n.dump(pw);
118                 }
119             pw.println("  }\n");
120         }
121         for(Node n : ihm.values()) {
122             if (done.get(n)!=null) continue;
123             n.dump(pw);
124         }
125         for(Node n : ihm.values()) n.edges(pw);
126         pw.println("}\n");
127     }
128
129 }