1 package org.catacomb.druid.util.tree;
2
3 import org.catacomb.interlish.structure.*;
4 import org.catacomb.report.E;
5
6
7 import java.util.ArrayList;
8 import java.util.HashMap;
9 import java.util.HashSet;
10 import java.util.ListIterator;
11
12
13 public class RelationTree implements PivotedTree {
14
15
16 ArrayListNode rootNode;
17
18 HashMap<Related, RelationNode> peers;
19
20 HashSet<String> relationTypes;
21
22 String[][] pivotOrders;
23
24 String[] pivotNames;
25
26
27 int iPivot;
28
29 int rootPolicy = Tree.AUTO_ROOT;
30
31 TreeChangeReporter tcReporter;
32
33
34
35 public RelationTree(ArrayList<Related> coll) {
36 init(coll);
37 setDefaultPivotOrders();
38 build(0);
39 }
40
41
42 public RelationTree(SingleParent sp) {
43 ArrayList<Related> coll = Trawler.trawlChildren(sp);
44 init(coll);
45 setDefaultPivotOrders();
46 build(0);
47 }
48
49
50 public TreeNode getRoot() {
51 return rootNode;
52 }
53
54
55 public void setRootPolicy(int ipol) {
56 rootPolicy = ipol;
57 }
58
59
60 public int getRootPolicy() {
61 return rootPolicy;
62 }
63
64
65 public String getPivotRelation() {
66 return pivotNames[iPivot];
67 }
68
69
70 public void init(ArrayList<Related> coll) {
71
72 peers = new HashMap<Related, RelationNode>();
73 relationTypes = new HashSet<String>();
74
75
76 ArrayList<RelationNode> nodes = addAll(coll);
77
78
79
80
81 resolveAll(nodes);
82
83
84 String[] sa = (relationTypes.toArray(new String[0]));
85 setPivotNames(sa);
86
87
88
89
90
91 }
92
93
94
95 private ArrayList<RelationNode> addAll(ArrayList<Related> coll) {
96 ArrayList<RelationNode> arl = new ArrayList<RelationNode>();
97
98 for (Related related : coll) {
99 RelationNode rnode = new RelationNode(null, related);
100 peers.put(related, rnode);
101 arl.add(rnode);
102 }
103 return arl;
104 }
105
106
107
108 private void resolveAll(ArrayList<RelationNode> coll) {
109 for (RelationNode rnode : coll) {
110 rnode.resolve(peers, relationTypes);
111 }
112 }
113
114
115
116
117
118 private void newItem(Related parent, Related child) {
119 RelationNode rnode = new RelationNode(parent, child);
120 peers.put(child, rnode);
121 rnode.resolve(peers, relationTypes);
122
123 if (tcReporter != null) {
124 tcReporter.nodeAddedUnder((RelationNode)(rnode.getParent()), rnode);
125 }
126
127 }
128
129
130
131 public void newBranch(Related parent, Related child) {
132 if (child instanceof SingleParent) {
133 ArrayList<Related> coll = Trawler.trawlChildren((SingleParent)child);
134 ArrayList<RelationNode> nodes = addAll(coll);
135 resolveAll(nodes);
136
137 } else {
138 newItem(parent, child);
139 }
140 build(iPivot);
141 }
142
143
144 public void childRemoved(Related parent, Related child) {
145 RelationNode rnParent = peers.get(parent);
146 RelationNode rnChild = peers.get(child);
147 peers.remove(child);
148 build(iPivot);
149 if (tcReporter != null) {
150 tcReporter.nodeRemoved(rnParent, rnChild);
151 }
152 }
153
154
155 public void setDefaultPivotOrders() {
156 String[] sa1 = (relationTypes.toArray(new String[0]));
157
158 String[] sa2 = new String[sa1.length];
159 for (int i = 0; i < sa1.length; i++) {
160 sa2[i] = sa1[sa1.length - 1 - i];
161 }
162 String[][] sa = { sa1, sa2 };
163 setPivotOrders(sa);
164 }
165
166
167
168 public void setPivotOrders(String[][] saa) {
169 pivotOrders = saa;
170 }
171
172
173
174 public String[] getPivotNames() {
175 if (pivotNames == null) {
176 String[] sa = { "pivot 1", "pivot 2" };
177 setPivotNames(sa);
178 }
179 return pivotNames;
180 }
181
182
183 public void setPivotNames(String[] sa) {
184 pivotNames = sa;
185 }
186
187
188 public void repivot(String s) {
189 int ibo = 0;
190 String[] sa = getPivotNames();
191 for (int i = 0; i < sa.length; i++) {
192 if (sa[i].equals(s)) {
193 ibo = i;
194 }
195 }
196 build(ibo);
197 }
198
199
200
201 public void build(int poin) {
202 int pivotOrder = poin;
203 if (pivotOrder >= pivotOrders.length) {
204 System.out.println("WARNING - requested non-existent pivot order " + pivotOrder);
205 pivotOrder = 0;
206 }
207 iPivot = pivotOrder;
208
209
210
211 ArrayList<RelationNode> rest = new ArrayList<RelationNode>();
212 rest.addAll(peers.values());
213
214 for (RelationNode rn : rest) {
215 rn.clearChildren();
216 }
217
218
219 String[] apo = pivotOrders[pivotOrder];
220
221
222 String srel = null;
223 if (apo.length > 0) {
224 srel = apo[0];
225 }
226 ArrayList<RelationNode> roots = getRoots(rest, srel);
227 if (rootNode == null) {
228 rootNode = new ArrayListNode(null, "root");
229 }
230
231 rootNode.setChildren(roots);
232
233
234
235
236
237
238
239
240
241 if (rest.isEmpty()) {
242
243 } else {
244 ArrayListNode aln = new ArrayListNode(rootNode, "other");
245 aln.setChildren(rest);
246 rootNode.addChild(aln);
247 }
248 }
249
250
251
252 public void treeify(ArrayList<RelationNode> roots, ArrayList<RelationNode> rest, String rel) {
253
254
255
256
257
258
259
260 for (RelationNode rnode : roots) {
261 rnode.subtreeify(null, rest, rel);
262 }
263
264 }
265
266
267
268
269
270 private ArrayList<RelationNode> getRoots(ArrayList<RelationNode> rest, String rel) {
271
272 if (rel != null) {
273
274 ListIterator<?> nodeiter = rest.listIterator();
275 while (nodeiter.hasNext()) {
276 RelationNode rnode = (RelationNode)(nodeiter.next());
277 if (rnode.fileAway(rel)) {
278 nodeiter.remove();
279 }
280 }
281 }
282
283
284
285
286 ArrayList<RelationNode> rwc = new ArrayList<RelationNode>();
287 ListIterator<?> restiter = rest.listIterator();
288 while (restiter.hasNext()) {
289 RelationNode rnode = (RelationNode)(restiter.next());
290 if (rnode.hasChildren()) {
291 rwc.add(rnode);
292 restiter.remove();
293 }
294 }
295 return rwc;
296 }
297
298
299
300 public Object[] getPathTo(Related child) {
301 ArrayList<Object> retal = new ArrayList<Object>();
302
303 Object[] ret = null;
304
305 RelationNode rnode = peers.get(child);
306
307 if (rnode == null) {
308 E.warning("relation tree has no peer for " + child + " ?");
309
310 } else {
311 String srel = getPivotRelation();
312
313 rnode = rnode.getParent(srel);
314
315
316
317
318 while (rnode != null) {
319 retal.add(0, rnode);
320 rnode = rnode.getParent(srel);
321 }
322 retal.add(0, rootNode);
323 ret = retal.toArray();
324 }
325 return ret;
326 }
327
328
329 public void setTreeChangeReporter(TreeChangeReporter tcr) {
330 tcReporter = tcr;
331 }
332
333
334 public Object[] getObjectPath(String s, boolean b) {
335 E.missing();
336 return null;
337 }
338
339
340
341 }