1 package org.catacomb.util;
2
3
4 import java.util.ArrayList;
5 import java.util.StringTokenizer;
6
7 import org.catacomb.interlish.structure.Tree;
8 import org.catacomb.interlish.structure.TreeChangeReporter;
9 import org.catacomb.interlish.structure.TreeNode;
10 import org.catacomb.report.E;
11
12 public class StringTree implements Tree, TreeNode {
13
14 String path;
15 String label;
16 ArrayList<TreeNode> children;
17
18 TreeNode parent;
19
20 boolean exclude = false;
21
22
23 public StringTree(String pth, String s) {
24 path = pth;
25 label = s;
26 children = new ArrayList<TreeNode>();
27 }
28
29
30
31 public void setExcluded() {
32 exclude = true;
33 }
34
35
36 public String toString() {
37 return label;
38 }
39
40 public String getLabel() {
41 return label;
42 }
43
44 public String getPath() {
45 return path;
46 }
47
48 public void addChild(TreeNode tn) {
49 children.add(tn);
50 if (tn instanceof StringTree) {
51 ((StringTree)tn).setParent(this);
52 } else if (tn instanceof StringTreeLeaf) {
53 ((StringTreeLeaf)tn).setParent(this);
54 } else {
55 E.error("wrong child type? " + tn);
56 }
57 }
58
59 public ArrayList<TreeNode> getChildren() {
60 return children;
61 }
62
63 public int nChildren() {
64 return children.size();
65 }
66
67
68 private StringTree getChildTree(String s) {
69 StringTree ret = null;
70 for (Object obj : children) {
71 if (obj instanceof StringTree && ((StringTree)obj).getLabel().equals(s)) {
72 ret = (StringTree)obj;
73 }
74 }
75 return ret;
76 }
77
78
79 public void addFromTokens(StringTokenizer st) {
80 if (st.hasMoreTokens()) {
81 String stok = st.nextToken();
82 if (st.hasMoreTokens()) {
83
84 StringTree sub = getChildTree(stok);
85 if (sub == null) {
86 sub = new StringTree(getPath() + stok + ".", stok);
87 addChild(sub);
88 }
89 sub.addFromTokens(st);
90
91
92 } else {
93 addChild(new StringTreeLeaf(stok));
94 }
95 }
96 }
97
98
99 public void compress() {
100 ArrayList<TreeNode> newChildren = new ArrayList<TreeNode>();
101 for (Object obj : children) {
102 if (obj instanceof StringTreeLeaf) {
103 newChildren.add((StringTreeLeaf)obj);
104 } else if (obj instanceof StringTree) {
105 Object oc = ((StringTree)obj).getCompressedForm();
106 if (oc instanceof StringTree) {
107 ((StringTree)oc).compress();
108 }
109 newChildren.add((TreeNode)oc);
110 }
111 }
112 children = newChildren;
113 }
114
115
116
117 public void partialFlatten() {
118 ArrayList<TreeNode> newChildren = new ArrayList<TreeNode>();
119
120 for (Object obj : children) {
121 if (obj instanceof StringTreeLeaf) {
122 newChildren.add((StringTreeLeaf)obj);
123
124
125 } else if (obj instanceof StringTree) {
126 StringTree ost = (StringTree)obj;
127 if (ost.nChildren() > 4) {
128 newChildren.add(ost);
129
130 } else {
131 newChildren.addAll(ost.getGrandchildrenAsChildren());
132 }
133 } else {
134 E.error("dropped child? " + obj);
135 }
136 }
137
138 children = newChildren;
139
140 for (Object oc : children) {
141 if (oc instanceof StringTree) {
142 ((StringTree)oc).partialFlatten();
143 }
144 }
145
146 }
147
148
149 private TreeNode getCompressedForm() {
150 TreeNode ret = this;
151
152 while (children.size() == 1) {
153 Object obj = children.get(0);
154
155 if (obj instanceof StringTree) {
156 StringTree ct = (StringTree)obj;
157 label = label + "." + ct.getLabel();
158 children = ct.getChildren();
159 path = ct.getPath();
160
161 } else if (obj instanceof StringTreeLeaf) {
162 ret = new StringTreeLeaf(label + "." + ((StringTreeLeaf)obj).getLabel());
163 break;
164 }
165 }
166
167 return ret;
168 }
169
170
171
172 public ArrayList<TreeNode> getGrandchildrenAsChildren() {
173 ArrayList<TreeNode> ret = new ArrayList<TreeNode>();
174 for (Object ob : children) {
175 if (ob instanceof StringTreeLeaf) {
176 ret.add((StringTreeLeaf)ob);
177
178 } else if (ob instanceof StringTree) {
179 StringTree chst = (StringTree)ob;
180
181 for (Object subch : chst.getChildren()) {
182 if (subch instanceof StringTreeLeaf) {
183 ret.add(new StringTreeLeaf(chst.getLabel() + "." + subch));
184
185 } else if (subch instanceof StringTree) {
186 ((StringTree)subch).prefixLabel(chst.getLabel() + ".");
187 ret.add((StringTree)subch);
188 }
189 }
190 }
191 }
192 return ret;
193 }
194
195
196
197 private void prefixLabel(String pfx) {
198 label = pfx + label;
199 }
200
201
202 public void print() {
203 print(" ");
204 }
205
206
207 private void print(String indent) {
208 System.out.println(indent + label + " (" + children.size() + "," + path + ")");
209 for (Object obj : children) {
210 if (obj instanceof String) {
211 System.out.println(indent + " " + obj);
212 } else {
213 ((StringTree)obj).print(indent + " ");
214 }
215 }
216 }
217
218
219 public TreeNode getRoot() {
220 return this;
221 }
222
223
224 public int getRootPolicy() {
225 return Tree.SHOW_ROOT;
226 }
227
228
229 public void setTreeChangeReporter(TreeChangeReporter tcr) {
230
231 }
232
233
234 public Object[] getObjectPath(String s, boolean b) {
235 E.warning("who needs the object path to " + s + " ?");
236 return null;
237 }
238
239
240 public void setParent(TreeNode obj) {
241 parent = obj;
242 }
243
244 public Object getParent() {
245 return parent;
246 }
247
248
249 public int getChildCount() {
250 return children.size();
251 }
252
253
254 public Object getChild(int index) {
255 return children.get(index);
256 }
257
258
259 public int getIndexOfChild(Object child) {
260 return children.indexOf(child);
261 }
262
263
264 public boolean isLeaf() {
265 return (children == null || children.size() == 0);
266 }
267
268 }