1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.trinidad.model;
20
21 import java.lang.reflect.Array;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.List;
25
26 import javax.faces.model.DataModel;
27
28 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
29 import org.apache.myfaces.trinidad.util.CollectionUtils;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93 public class ChildPropertyMenuModel extends MenuModel
94 {
95
96
97
98
99
100
101
102
103
104
105
106
107 public ChildPropertyMenuModel(Object instance, String childProperty, Object focusRowKey)
108 {
109 this();
110 setChildProperty(childProperty);
111 setWrappedData(instance);
112 this._focusRowKey = focusRowKey;
113 }
114
115
116
117
118
119
120 public ChildPropertyMenuModel()
121 {
122 Node root = new Node(null);
123 _path.add(root);
124 }
125
126
127
128
129 @Override
130 public Object getRowKey()
131 {
132 final int sz = _path.size() - 1;
133 Object lastRowkey = _getRowKey();
134 if ((sz == 0) && (lastRowkey == null))
135 return null;
136
137
138
139
140 List<Object> path = new ArrayList<Object>(sz+1);
141 if (sz > 0)
142 {
143 for(int i=0; i<sz; i++)
144 {
145 Node node = _getNode(i);
146 path.add(node.childModel.getRowKey());
147 }
148 }
149 path.add(lastRowkey);
150 return path;
151 }
152
153
154
155
156
157 @SuppressWarnings("unchecked")
158 @Override
159 public void setRowKey(Object rowKey)
160 {
161 Node root = _getNode(0);
162 _path.clear();
163 _path.add(root);
164
165 List<Object> path = (List<Object>) rowKey;
166 if ((path == null) || (path.size() == 0))
167 {
168 setRowIndex(-1);
169 return;
170 }
171
172 int lastIndex = path.size() - 1;
173 for(int i=0; i<lastIndex; i++)
174 {
175 Object pathKey = path.get(i);
176 _setRowKey(pathKey);
177 enterContainer();
178 }
179
180 _setRowKey(path.get(lastIndex));
181 }
182
183 @SuppressWarnings("unchecked")
184 @Override
185 public Object getContainerRowKey(Object childKey)
186 {
187 List<Object> path = (List<Object>) childKey;
188 if ((path == null) || (path.size() <= 1))
189 return null;
190
191
192
193 return CollectionUtils.newSerializableList(path.subList(0, path.size() - 1));
194 }
195
196 @Override
197 public int getRowCount()
198 {
199 return _getModel().getRowCount();
200 }
201
202 @Override
203 public Object getRowData()
204 {
205 return _getModel().getRowData();
206 }
207
208 @Override
209 public boolean isRowAvailable()
210 {
211 return _getModel().isRowAvailable();
212 }
213
214 @Override
215 public boolean isContainer()
216 {
217 Object rowData = getRowData();
218 Object value = getChildData(rowData);
219
220 if (value != null)
221 {
222 if (value instanceof Collection<?>)
223 {
224 return !((Collection<?>)value).isEmpty();
225 }
226 else if (value.getClass().isArray())
227 {
228 return Array.getLength(value) > 0;
229 }
230 else if (value instanceof DataModel)
231 {
232 return ((DataModel)value).getRowCount() > 0;
233 }
234 }
235
236 return value != null;
237 }
238
239 @Override
240 public void enterContainer()
241 {
242 Object rowData = getRowData();
243 if (rowData == null)
244 throw new IllegalStateException(_LOG.getMessage("NULL_ROWDATA"));
245 Node node = new Node(rowData);
246 _path.add(node);
247 }
248
249 @Override
250 public void exitContainer()
251 {
252 int sz = _path.size();
253 if (sz > 1)
254 _path.remove(sz - 1);
255 else
256 throw new IllegalStateException(_LOG.getMessage("CANNOT_EXIT_ROOT_CONTAINER"));
257 }
258
259
260
261
262 @Override
263 public Object getWrappedData()
264 {
265 return _wrappedData;
266 }
267
268
269
270
271
272 @Override
273 public void setWrappedData(Object data)
274 {
275 Node root = _getNode(0);
276 root.childModel = ModelUtils.toCollectionModel(data);
277 setRowKey(null);
278 _wrappedData = data;
279 }
280
281
282
283
284 public final String getChildProperty()
285 {
286 return _childProperty;
287 }
288
289
290
291
292 public final void setChildProperty(String childProperty)
293 {
294 _childProperty = childProperty;
295 }
296
297 @Override
298 public int getRowIndex()
299 {
300 return _getModel().getRowIndex();
301 }
302
303 @Override
304 public void setRowIndex(int rowIndex)
305 {
306 _getModel().setRowIndex(rowIndex);
307 }
308
309 @Override
310 public boolean isSortable(String property)
311 {
312 return _getModel().isSortable(property);
313 }
314
315 @Override
316 public List<SortCriterion> getSortCriteria()
317 {
318 return _getModel().getSortCriteria();
319 }
320
321 @Override
322 public void setSortCriteria(List<SortCriterion> criteria)
323 {
324 _getModel().setSortCriteria(criteria);
325 }
326
327
328
329
330
331
332
333
334 protected Object getChildData(Object parentData)
335 {
336 String prop = getChildProperty();
337 if (prop == null)
338 return null;
339
340 return SortableModel.__resolveProperty(parentData, prop);
341 }
342
343
344
345
346
347
348 protected CollectionModel createChildModel(Object childData)
349 {
350 CollectionModel model = ModelUtils.toCollectionModel(childData);
351 model.setRowIndex(-1);
352 return model;
353 }
354
355 private Object _getRowKey()
356 {
357 return _getModel().getRowKey();
358 }
359
360 private void _setRowKey(Object key)
361 {
362 _getModel().setRowKey(key);
363 }
364
365 private Node _getCurrentNode()
366 {
367 return _getNode(_path.size() - 1);
368 }
369
370 private Node _getNode(int index)
371 {
372 return _path.get(index);
373 }
374
375 private CollectionModel _getModel()
376 {
377 Node node = _getCurrentNode();
378 CollectionModel model = node.childModel;
379
380 if (model == null)
381 {
382 Object value = getChildData(node.parentData);
383 model = createChildModel(value);
384 node.childModel = model;
385 }
386 return model;
387 }
388
389 public Object getFocusRowKey()
390 {
391 return _focusRowKey;
392 }
393
394 public void setFocusRowKey(Object focusRowKey)
395 {
396 _focusRowKey = focusRowKey;
397 }
398
399 private static final class Node
400 {
401 public Node(Object parentData)
402 {
403 this.parentData = parentData;
404 }
405
406 public final Object parentData;
407 CollectionModel childModel = null;
408 }
409
410 private final List<Node> _path = new ArrayList<Node>(5);
411 private String _childProperty;
412 private Object _wrappedData;
413 private Object _focusRowKey;
414 private static final TrinidadLogger _LOG =
415 TrinidadLogger.createTrinidadLogger(ChildPropertyMenuModel.class);
416 }