1
2
3
4 package org.extremecomponents.tree.model;
5
6 import java.util.ArrayList;
7 import java.util.Iterator;
8 import java.util.List;
9
10 import org.apache.commons.beanutils.BeanUtils;
11 import org.apache.commons.beanutils.PropertyUtils;
12
13 import org.apache.commons.logging.Log;
14 import org.apache.commons.logging.LogFactory;
15
16 import org.extremecomponents.table.model.ParameterRegistry;
17
18 import org.extremecomponents.tree.bean.TreeNode;
19
20
21 /***
22 * org.extremecomponents.tree.model.TreeModelUtils.java -
23 *
24 * @author phorn
25 */
26 public class TreeModelUtils
27 {
28 private static Log logger = LogFactory.getLog(TreeModelUtils.class);
29
30 /***
31 * Recursively loads the tree structure into the treeList attribute and sets the
32 * treeList as the collection to use.
33 * @param model
34 * @param inputList
35 * @throws Exception
36 */
37 public static List loadTreeStructure(TreeModel model, List inputList) throws Exception
38 {
39 List result = new ArrayList();
40
41 List searchList = new ArrayList();
42 searchList.addAll(inputList);
43
44 for (Iterator iter = searchList.iterator(); iter.hasNext();)
45 {
46 Object bean = iter.next();
47
48 if (BeanUtils.getProperty(bean, model.getParentAttribute()) == null)
49 {
50
51 TreeNode node = new TreeNode(bean, getBeanId(model, bean), 0);
52 result.add(node);
53 iter.remove();
54 loadChildren(model, result, searchList, node, 0);
55 }
56 }
57
58 return result;
59 }
60
61 /***
62 * @param model
63 * @param displayList
64 * @param searchList
65 * @param node
66 * @param currentDepth
67 * @throws Exception
68 */
69 public static void loadChildren(TreeModel model, List displayList, List searchList, TreeNode node, int currentDepth) throws Exception
70 {
71 currentDepth++;
72
73 List subList = new ArrayList();
74 subList.addAll(searchList);
75
76 Object id = node.getIdentifier();
77 String key = getNodeKey(model, id);
78
79 if (model.getOpenNodes().get(key) != null)
80 {
81 node.setOpen(true);
82 }
83 else
84 {
85 node.setOpen(false);
86 }
87
88 for (Iterator iter = subList.iterator(); iter.hasNext();)
89 {
90 Object bean = iter.next();
91
92 if (nodeIsBeanParent(model, node, bean))
93 {
94 TreeNode childNode = new TreeNode(bean, getBeanId(model, bean), currentDepth);
95 node.addChild(childNode);
96 childNode.setParent(node);
97 iter.remove();
98
99 if (isOpen(model, node, true))
100 {
101 displayList.add(childNode);
102 }
103
104 loadChildren(model, displayList, subList, childNode, currentDepth);
105 }
106 }
107 }
108
109 /***
110 * Used by the filter function to add back the filtered out parents.
111 * @param model
112 * @param searchList
113 * @return
114 * @throws Exception
115 */
116 public static List findParents(TreeModel model, List searchList) throws Exception
117 {
118 logger.debug("TreeModel.findParents()");
119
120 List result = new ArrayList();
121
122 for (Iterator iter = searchList.iterator(); iter.hasNext();)
123 {
124 Object bean = iter.next();
125
126 if (!result.contains(bean))
127 {
128 result.add(bean);
129 }
130
131 findBeanParents(model, result, bean);
132 }
133
134 return result;
135 }
136
137 /***
138 * Recursive call used by the filter function to add back the filtered out parents.
139 * @param model
140 * @param parents
141 * @param bean
142 * @throws Exception
143 */
144 public static void findBeanParents(TreeModel model, List parents, Object bean) throws Exception
145 {
146 Object parent = PropertyUtils.getProperty(bean, model.getParentAttribute());
147
148 if (parent == null)
149 {
150 return;
151 }
152 else
153 {
154 if (!parents.contains(parent))
155 {
156 parents.add(parent);
157 findBeanParents(model, parents, parent);
158 }
159 }
160 }
161
162 /***
163 * Used by the filter function to add back the filtered out children.
164 * @param model
165 * @param displayList
166 * @throws Exception
167 */
168 public static void addClosedChildren(TreeModel model, List displayList) throws Exception
169 {
170 logger.debug("TreeModel.addClosedChildren()");
171
172 List parents = new ArrayList();
173 parents.addAll(displayList);
174
175 for (Iterator iter = parents.iterator(); iter.hasNext();)
176 {
177 TreeNode node = (TreeNode) iter.next();
178
179 if ((node.getChildren() == null) || (node.getChildren().size() == 0))
180 {
181 addChildren(model, displayList, node);
182 }
183 }
184 }
185
186 /***
187 * Recursive call used by the filter function to add back the filtered out children
188 * but keeps them collapsed unless they have been openned manually be the open parameter.
189 * @param model
190 * @param displayList
191 * @param node
192 * @throws Exception
193 */
194 public static void addChildren(TreeModel model, List displayList, TreeNode node) throws Exception
195 {
196 for (Iterator iter = model.getTableCollection().iterator(); iter.hasNext();)
197 {
198 Object bean = iter.next();
199
200 if (nodeIsBeanParent(model, node, bean))
201 {
202 TreeNode childNode = new TreeNode(bean, getBeanId(model, bean), node.getDepth() + 1);
203 node.addChild(childNode);
204
205 Object id = node.getIdentifier();
206 String openParam = (String) model.getOpenNodes().get(getNodeKey(model, id));
207
208 if (isOpen(model, node, false) || "true".equals(openParam))
209 {
210 node.setOpen(true);
211
212 int parentPosition = displayList.indexOf(node);
213 displayList.add(parentPosition + 1, childNode);
214 }
215
216 addChildren(model, displayList, childNode);
217 }
218 }
219 }
220
221 /***
222 * @param model
223 * @param node
224 * @param bean
225 * @return
226 * @throws Exception
227 */
228 public static boolean nodeIsBeanParent(TreeModel model, TreeNode node, Object bean) throws Exception
229 {
230 Object parent = PropertyUtils.getProperty(bean, model.getParentAttribute());
231
232 if (parent == null)
233 {
234 return false;
235 }
236
237 Object nodeId = node.getIdentifier();
238 Object parentId = getBeanId(model, parent);
239
240 return (node.getBean().equals(parent) || nodeId.equals(parentId));
241 }
242
243 /***
244 * @param model
245 * @param bean
246 * @return
247 * @throws Exception
248 */
249 public static Object getBeanId(TreeModel model, Object bean) throws Exception
250 {
251 return PropertyUtils.getProperty(bean, model.getIdentifier());
252 }
253
254 /***
255 * Find out if the node and all parents are open.
256 * @param model
257 * @param node
258 * @param filterControlled
259 * @return
260 */
261 public static boolean isOpen(TreeModel model, TreeNode node, boolean filterControlled)
262 {
263 if (filterControlled && model.getFilterHandler().doFilter() && !model.getFilterHandler().doClear())
264 {
265 node.setOpen(true);
266
267 return true;
268 }
269
270 if (!node.isOpen())
271 {
272 return false;
273 }
274
275 if (node.getParent() == null)
276 {
277 return true;
278 }
279
280 return isOpen(model, node.getParent(), filterControlled);
281 }
282
283 /***
284 * @param model
285 * @param id value of the node.
286 * @return Returns the parameter key used to indicate this node is open.
287 */
288 public static String getNodeKey(TreeModel model, Object id)
289 {
290 return model.getTableKey() + ParameterRegistry.OPEN + id;
291 }
292 }