IdentityHashMap<ToGraphViz,Node> ihm = new IdentityHashMap<ToGraphViz,Node>();
HashMap<Node,Group> groups = new HashMap<Node,Group>();
- public class Group {
+ public class Group extends Node {
+ private final int idx = master_idx++;
+ public boolean cluster = false;
+ public boolean primary = true;
public Group() { }
public void add(Node n) { groups.put(n, this); }
+ public String name() { return cluster?("cluster_"+idx):("subgraph_"+idx); }
+ public boolean simple() { return false; }
+ public void dump(PrintWriter pw, IdentityHashMap<Node,Node> done) {
+ Group g = this;
+ if (done.get(g)!=null) return;
+ done.put(g,g);
+ pw.println(" subgraph "+name()+" { rank=same;\n");
+ pw.println(" label=\""+StringUtil.escapify(label.toString(), "\\\"\r\n")+"\";\n");
+ pw.println(" color="+g.color+";\n");
+ pw.println(" shape="+g.shape+";\n");
+ for(Node n : groups.keySet())
+ if (groups.get(n)==g)
+ n.dump(pw, done);
+ pw.println(" }\n");
+ }
}
private static int master_idx=0;
+
public class Node {
private final int idx = master_idx++;
public String label;
+ public String comment;
public boolean directed = false;
public String color="black";
+ public String fill="white";
+ public String shape="ellipse";
public ArrayList<Node> edges = new ArrayList<Node>();
public ArrayList<Object> labels = new ArrayList<Object>();
public ArrayList<Node> inbound = new ArrayList<Node>();
labels.add(label);
n.inbound.add(this);
}
+ public String getParentName() {
+ if (inbound.size()==1 && inbound.get(0).simple())
+ return inbound.get(0).getParentName();
+ return name();
+ }
public String name() {
if (inbound.size()==1 && inbound.get(0).simple())
- return inbound.get(0).name()+":node_"+idx;
+ return inbound.get(0).getParentName()+":node_"+idx;
return "node_"+idx;
}
public void edges(PrintWriter pw) {
for(int i=0; i<edges.size(); i++) {
Node n = edges.get(i);
Object label = labels.get(i);
- pw.println(" "+name()+" -> " + n.name() + " [color="+color+" " +(label==null?"":("label=\""+label+"\""))+ "];\n");
+ pw.println(" "+name()+" -> " + n.name() + " [color="+color+" "
+ +(label==null?"":("label=\""+StringUtil.escapify(label.toString(), "\\\"\r\n")+"\""))+ "];\n");
}
}
public int numEdges() { return edges.size(); }
if (n.inbound.size() > 1) { simple = false; break; }
return simple;
}
- public void dump(PrintWriter pw) {
+ public void dump(PrintWriter pw, IdentityHashMap<Node,Node> done) {
+ if (done.get(this)!=null) return;
+ done.put(this, this);
if (inbound.size() > 0) {
boolean good = false;
for(Node n : inbound)
if (!first) pw.print("|");
first = false;
pw.print("<node_"+n.idx+">");
- pw.print(StringUtil.escapify(n.label,"\\\""));
+ pw.print(StringUtil.escapify(n.label,"\\\"\r\n"));
}
if (!complex) pw.print("}");
- pw.print("\"");
+ pw.print("\" ");
} else {
pw.print(" label=\"");
- pw.print(StringUtil.escapify(label,"\\\""));
- pw.print("\"");
+ pw.print(StringUtil.escapify(label,"\\\"\r\n"));
+ pw.print("\" ");
}
pw.print("color="+color);
+ if (comment!=null) pw.print(" comment=\""+StringUtil.escapify(comment,"\\\"\r\n")+"\" ");
pw.print("];\n");
}
}
return n;
}
+ public Group createGroup(ToGraphViz o) {
+ Group n = (Group)ihm.get(o);
+ if (n!=null) return n;
+ n = new Group();
+ ihm.put(o, n);
+ return n;
+ }
+
public static interface ToGraphViz {
public Node toGraphViz(GraphViz gv);
public boolean isTransparent();
public boolean isHidden();
}
+ public void show() throws IOException {
+ Runtime.getRuntime().exec(new String[] { "dot", "-Tsvg" });
+ }
+
+ public void dump(OutputStream os) { dump(new PrintWriter(new OutputStreamWriter(os))); }
public void dump(PrintWriter pw) {
IdentityHashMap<Node,Node> done = new IdentityHashMap<Node,Node>();
- pw.println("digraph G { rankdir=LR; \n");
- for(Group g : groups.values()) {
- pw.println(" { rank=same;\n");
- for(Node n : groups.keySet())
- if (groups.get(n)==g) {
- done.put(n,n);
- n.dump(pw);
- }
- pw.println(" }\n");
- }
+ pw.println("digraph G { rankdir=LR; ordering=out; compound=true; \n");
+ for(Group g : groups.values())
+ if (g.primary)
+ g.dump(pw, done);
for(Node n : ihm.values()) {
if (done.get(n)!=null) continue;
- n.dump(pw);
+ if (n instanceof Group) continue;
+ n.dump(pw, done);
}
for(Node n : ihm.values()) n.edges(pw);
pw.println("}\n");
+ pw.flush();
}
}