1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.trinidad.component;
20
21 import java.util.AbstractMap;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.List;
25
26 import java.util.Map;
27 import java.util.Set;
28
29 import javax.faces.component.UIComponent;
30
31 import javax.faces.component.visit.VisitCallback;
32 import javax.faces.component.visit.VisitContext;
33
34 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
35 import org.apache.myfaces.trinidad.model.CollectionModel;
36 import org.apache.myfaces.trinidad.model.LocalRowKeyIndex;
37 import org.apache.myfaces.trinidad.model.ModelUtils;
38 import org.apache.myfaces.trinidad.model.RowKeySet;
39 import org.apache.myfaces.trinidad.model.TreeLocalRowKeyIndex;
40 import org.apache.myfaces.trinidad.model.TreeModel;
41 import org.apache.myfaces.trinidad.util.StringUtils;
42
43
44
45
46
47
48
49 @JSFComponent
50 public abstract class UIXHierarchy extends UIXCollection implements CollectionComponent, LocalRowKeyIndex,
51 TreeLocalRowKeyIndex
52 {
53
54
55
56 protected UIXHierarchy(String rendererType)
57 {
58 super(rendererType);
59 }
60
61
62 protected UIXHierarchy()
63 {
64 this(null);
65 }
66
67 @Override
68 public CollectionModel createCollectionModel(CollectionModel current, Object value)
69 {
70 TreeModel model = ModelUtils.toTreeModel(value);
71 model.setRowKey(null);
72 return model;
73 }
74
75
76
77
78
79
80 public int getFirst()
81 {
82 return 0;
83 }
84
85
86
87
88
89
90 public int getRows()
91 {
92 return 0;
93 }
94
95
96
97
98
99
100
101
102
103 public final void enterContainer()
104 {
105 preRowDataChange();
106 getTreeModel().enterContainer();
107 postRowDataChange();
108 }
109
110
111
112
113
114
115
116
117 public final void exitContainer()
118 {
119 preRowDataChange();
120 getTreeModel().exitContainer();
121 postRowDataChange();
122 }
123
124
125
126
127
128
129 public final boolean isContainer()
130 {
131 return getTreeModel().isContainer();
132 }
133
134
135
136
137
138
139 public boolean isContainerEmpty()
140 {
141 return getTreeModel().isContainerEmpty();
142 }
143
144
145
146
147
148
149 public int getDepth()
150 {
151 return getTreeModel().getDepth();
152 }
153
154
155
156
157
158
159 public int getDepth(Object rowKey)
160 {
161 return getTreeModel().getDepth(rowKey);
162 }
163
164
165
166
167
168 public Object getContainerRowKey()
169 {
170 return getTreeModel().getContainerRowKey();
171 }
172
173
174
175
176
177 public Object getContainerRowKey(Object childKey)
178 {
179 return getTreeModel().getContainerRowKey(childKey);
180 }
181
182
183
184
185
186 public List<Object> getAllAncestorContainerRowKeys(Object childRowKey)
187 {
188 return getTreeModel().getAllAncestorContainerRowKeys(childRowKey);
189 }
190
191
192
193
194
195
196
197
198
199
200
201 public boolean isChildCollectionLocallyAvailable()
202 {
203 return getTreeModel().isChildCollectionLocallyAvailable();
204 }
205
206
207
208
209
210
211
212
213 public boolean isChildCollectionLocallyAvailable(int index)
214 {
215 return getTreeModel().isChildCollectionLocallyAvailable(index);
216 }
217
218
219
220
221
222
223
224
225 public boolean isChildCollectionLocallyAvailable(Object rowKey)
226 {
227 return getTreeModel().isChildCollectionLocallyAvailable(rowKey);
228 }
229
230
231
232
233
234
235
236
237
238
239
240 public boolean areRowsLocallyAvailable(int startIndex, int rowCount,
241 RowKeySet disclosedRowKeys)
242 {
243 return getTreeModel().areRowsLocallyAvailable(startIndex, rowCount, disclosedRowKeys);
244 }
245
246
247
248
249
250
251
252
253
254
255
256 public boolean areRowsLocallyAvailable(Object startRowKey, int rowCount,
257 RowKeySet disclosedRowKeys)
258 {
259 return getTreeModel().areRowsLocallyAvailable(startRowKey, rowCount, disclosedRowKeys);
260 }
261
262
263
264
265
266
267
268
269
270
271 public boolean areRowsLocallyAvailable(int rowCount,
272 RowKeySet disclosedRowKeys)
273 {
274 return getTreeModel().areRowsLocallyAvailable(rowCount, disclosedRowKeys);
275 }
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291 @Override
292 protected Map<String, Object> createVarStatusMap()
293 {
294 final Map<String, Object> map = super.createVarStatusMap();
295 return new AbstractMap<String, Object>()
296 {
297 @Override
298 public Object get(Object key)
299 {
300 if("hierarchicalIndex".equals(key))
301 {
302 return _getHierarchicalIndex().toArray();
303 }
304 if("hierarchicalLabel".equals(key))
305 {
306 List<Integer> rowIndices = _getHierarchicalIndex();
307 if(rowIndices.size() == 0)
308 return "";
309
310 Integer[] indexArray = new Integer[rowIndices.size()];
311
312 for(int i = 0; i < rowIndices.size(); i++)
313 {
314 indexArray[i] = Integer.valueOf(rowIndices.get(i).intValue()+1);
315 }
316 return StringUtils.join(indexArray, '.');
317 }
318 return map.get(key);
319 }
320
321
322
323
324 private List<Integer> _getHierarchicalIndex()
325 {
326 Object rowKey = getRowKey();
327 if(rowKey == null)
328 return Collections.emptyList();
329
330 TreeModel treeModel = getTreeModel();
331 List<Integer> rowIndices = new ArrayList<Integer>();
332
333
334
335 try
336 {
337 rowIndices.add(treeModel.getRowIndex());
338
339 Object childRowKey = treeModel.getContainerRowKey(rowKey);
340 while(childRowKey != null)
341 {
342 treeModel.setRowKey(childRowKey);
343 rowIndices.add(treeModel.getRowIndex());
344 childRowKey = treeModel.getContainerRowKey(childRowKey);
345 }
346 Collections.reverse(rowIndices);
347 }
348 finally
349 {
350
351 treeModel.setRowKey(rowKey);
352 }
353 return rowIndices;
354 }
355
356 @Override
357 public Set<Map.Entry<String, Object>> entrySet()
358 {
359 return map.entrySet();
360 }
361 };
362 }
363
364
365
366
367 protected final TreeModel getTreeModel()
368 {
369 TreeModel model = (TreeModel) getCollectionModel();
370 return model;
371 }
372
373 @Override
374 protected List<UIComponent> getStamps()
375 {
376 UIComponent nodeStamp = getFacet("nodeStamp");
377 if (nodeStamp != null)
378 return Collections.singletonList(nodeStamp);
379 else
380 return Collections.emptyList();
381 }
382
383 abstract public Object getFocusRowKey();
384
385 protected final boolean visitLevel(
386 VisitContext visitContext,
387 VisitCallback callback,
388 List<UIComponent> stamps)
389 {
390 if (getRowCount() != 0)
391 {
392 if (!stamps.isEmpty())
393 {
394 int oldRow = getRowIndex();
395 int first = getFirst();
396 int last = TableUtils.getLast(this, first);
397
398 try
399 {
400 for (int i = first; i <= last; i++)
401 {
402 setRowIndex(i);
403
404 for (UIComponent currStamp : stamps)
405 {
406
407 if (UIXComponent.visitTree(visitContext, currStamp, callback))
408 return true;
409 }
410 }
411 }
412 finally
413 {
414 setRowIndex(oldRow);
415 }
416 }
417 }
418
419 return false;
420 }
421
422 protected final boolean visitHierarchy(
423 VisitContext visitContext,
424 VisitCallback callback,
425 List<UIComponent> stamps,
426 RowKeySet disclosedRowKeys)
427 {
428 int oldRow = getRowIndex();
429 int first = getFirst();
430 int last = TableUtils.getLast(this, first);
431
432 try
433 {
434 for(int i = first; i <= last; i++)
435 {
436 setRowIndex(i);
437 if (!stamps.isEmpty())
438 {
439 for (UIComponent currStamp : stamps)
440 {
441
442 if (UIXComponent.visitTree(visitContext, currStamp, callback))
443 return true;
444 }
445 }
446
447 if (isContainer() && ((disclosedRowKeys == null) || disclosedRowKeys.isContained()))
448 {
449 enterContainer();
450
451 try
452 {
453
454 if (visitHierarchy(visitContext, callback, stamps, disclosedRowKeys))
455 return true;
456 }
457 finally
458 {
459 exitContainer();
460 }
461 }
462 }
463 }
464 finally
465 {
466 setRowIndex(oldRow);
467 }
468
469 return false;
470 }
471 }