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