1b5ffc0b176ed04cc41bff0e32413b29462e0169
[sbp.git] / src / edu / berkeley / sbp / util / PrintableTree.java
1 package edu.berkeley.sbp.util;
2 import edu.berkeley.sbp.*;
3 import edu.berkeley.sbp.util.*;
4 import java.io.*;
5 import java.util.*;
6 import java.lang.reflect.*;
7
8 public abstract class PrintableTree<T extends PrintableTree> implements Iterable<T>, ToJava /*, ToHTML*/, GraphViz.ToGraphViz {
9
10     protected abstract Object head();
11     protected abstract String headToString();
12     protected abstract String headToJava();    
13     protected abstract String left();
14     protected abstract String right();
15     protected abstract boolean ignoreSingleton();
16
17     private static final int MAXCHARS=40;
18
19     private boolean basic() { return toString().length() < MAXCHARS; }
20     public String toPrettyString() { return toPrettyString("\n"); }
21     public StringBuffer toPrettyString(StringBuffer sb) { sb.append(toPrettyString()); return sb; }
22     private String toPrettyString(String nl) {
23         String str = toString();
24         if (str.length() < MAXCHARS) return str;
25         String head = headToString();
26         StringBuffer ret = new StringBuffer();
27
28         Iterator<T> iterator = iterator();
29         if (!iterator.hasNext()) return head==null ? (left()+right()) : head;
30         PrintableTree t0 = iterator.next();
31         if (!iterator.hasNext() && ignoreSingleton())
32             return t0.toPrettyString(nl);
33
34         ret.append(head==null?(left()+" "):(head+":"+nl));
35         boolean first = true;
36         int len = 0;
37         for(T t : this) {
38             String s = t.basic() ? t.toString() : t.toPrettyString(nl+"  ");
39             if (!first) {
40                 if (!t.basic())                ret.append(nl);
41                 if (s.length()+len>MAXCHARS) { ret.append(nl); len = 0; }
42                 else                         { ret.append(" "); len++; }
43             }
44             first = false;
45             ret.append(s);
46             len += s.length();
47         }
48         if (head==null) ret.append(" "+right());
49         return ret.toString();
50     }
51
52     private String cached = null;
53     public String toString() {
54         if (cached!=null) return cached;
55         StringBuffer ret = new StringBuffer();
56         int count=0;
57         for(T t : this) {
58             count++;
59             String q = t==null ? "null" : t.toString();
60             if (q.length() > 0) { ret.append(q); ret.append(" "); }
61         }
62         if (count==1 && ignoreSingleton()) { return cached = ret.toString().trim(); }
63         String tail = ret.toString().trim();
64         String head = headToString();
65         String h = (head!=null && !head.toString().equals("")) ? (tail.length() > 0 ? head+":" : head+"") : "";
66         if (tail.length() > 0) tail = left() + tail + right();
67         return cached = h + tail;
68     }
69
70     /** append Java code to <tt>sb</tt> which evaluates to this instance */
71     public void toJava(StringBuffer sb) {
72         sb.append("new "+this.getClass().getName()+"(null, ");
73         String head = headToJava();
74         sb.append(head);
75         sb.append(", new "+this.getClass().getName()+"[] { ");
76         boolean first = true;
77         for(T t : this) {
78             if (!first) sb.append(",\n        ");
79             if (t==null)   sb.append("null");
80             else           t.toJava(sb);
81             first = false;
82         }
83         sb.append("})");
84     }
85
86     public GraphViz.Node toGraphViz(GraphViz gv) {
87         if (gv.hasNode(this)) return gv.createNode(this);
88         GraphViz.Node n = gv.createNode(this);
89         n.label = head()==null ? "" : head().toString();
90         for(T t : this) n.edge(t, null);
91         return n;
92     }
93     public boolean isTransparent() { return false; }
94     public boolean isHidden() { return false; }
95 }