1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.uif.container;
17
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22
23 import org.apache.commons.lang.StringUtils;
24 import org.kuali.rice.core.api.util.tree.Node;
25 import org.kuali.rice.core.api.util.tree.Tree;
26 import org.kuali.rice.krad.datadictionary.parse.BeanTag;
27 import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
28 import org.kuali.rice.krad.datadictionary.parse.BeanTags;
29 import org.kuali.rice.krad.uif.UifConstants;
30 import org.kuali.rice.krad.uif.component.BindingInfo;
31 import org.kuali.rice.krad.uif.component.Component;
32 import org.kuali.rice.krad.uif.component.DataBinding;
33 import org.kuali.rice.krad.uif.element.Message;
34 import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle;
35 import org.kuali.rice.krad.uif.util.ComponentUtils;
36 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
37
38
39
40
41
42
43
44 @BeanTags({@BeanTag(name = "treeGroup-bean", parent = "Uif-TreeGroup"),
45 @BeanTag(name = "treeSection-bean", parent = "Uif-TreeSection"),
46 @BeanTag(name = "treeSubSection-bean", parent = "Uif-TreeSubSection")})
47 public class TreeGroup extends Group implements DataBinding {
48 private static final long serialVersionUID = 5841343037089286740L;
49
50 private String propertyName;
51 private BindingInfo bindingInfo;
52
53 private Map<Class<?>, NodePrototype> nodePrototypeMap;
54 private NodePrototype defaultNodePrototype;
55
56 private Tree<Group, Message> treeGroups;
57
58 private org.kuali.rice.krad.uif.widget.Tree tree;
59
60 public TreeGroup() {
61 super();
62
63 treeGroups = new Tree<Group, Message>();
64 }
65
66
67
68
69
70
71
72
73
74
75
76 @Override
77 public void performInitialization(Object model) {
78 setFieldBindingObjectPath(getBindingInfo().getBindingObjectPath());
79
80 super.performInitialization(model);
81
82 if (bindingInfo != null) {
83 bindingInfo.setDefaults(ViewLifecycle.getActiveLifecycle().getView(), getPropertyName());
84 }
85
86
87 }
88
89 @Override
90 public void performApplyModel(Object model, Component parent) {
91 super.performApplyModel(model, parent);
92
93 buildTreeGroups(model);
94 }
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110 protected void buildTreeGroups(Object model) {
111
112 Tree<Object, String> treeData = ObjectPropertyUtils.getPropertyValue(model, getBindingInfo().getBindingPath());
113
114
115 Tree<Group, Message> treeGroups = new Tree<Group, Message>();
116
117 String bindingPrefix = getBindingInfo().getBindingPrefixForNested();
118 Node<Group, Message> rootNode = buildTreeNode(treeData.getRootElement(),
119 bindingPrefix +
120 treeGroups.setRootElement(rootNode);
121
122 setTreeGroups(treeGroups);
123 }
124
125 protected Node<Group, Message> buildTreeNode(Node<Object, String> nodeData, String bindingPrefix,
126 String parentNode) {
127 if (nodeData == null) {
128 return null;
129 }
130
131 Node<Group, Message> node = new Node<Group, Message>();
132 node.setNodeType(nodeData.getNodeType());
133
134 NodePrototype prototype = getNodePrototype(nodeData);
135
136 Message message = ComponentUtils.copy(prototype.getLabelPrototype(), parentNode);
137 ComponentUtils.pushObjectToContext(message, UifConstants.ContextVariableNames.NODE, nodeData);
138 message.setMessageText(nodeData.getNodeLabel());
139 node.setNodeLabel(message);
140
141 Group nodeGroup = ComponentUtils.copyComponent(prototype.getDataGroupPrototype(), bindingPrefix + ".data",
142 parentNode);
143 ComponentUtils.pushObjectToContext(nodeGroup, UifConstants.ContextVariableNames.NODE, nodeData);
144
145 String nodePath = bindingPrefix + ".data";
146 if (StringUtils.isNotBlank(getBindingInfo().getBindingObjectPath())) {
147 nodePath = getBindingInfo().getBindingObjectPath() + "." + nodePath;
148 }
149 ComponentUtils.pushObjectToContext(nodeGroup, UifConstants.ContextVariableNames.NODE_PATH, nodePath);
150 node.setData(nodeGroup);
151
152 List<Node<Group, Message>> nodeChildren = new ArrayList<Node<Group, Message>>();
153
154 int childIndex = 0;
155 for (Node<Object, String> childDataNode : nodeData.getChildren()) {
156 String nextBindingPrefix = bindingPrefix + ".children[" + childIndex + "]";
157 Node<Group, Message> childNode = buildTreeNode(childDataNode, nextBindingPrefix,
158 "_node_" + childIndex + ("root".equals(parentNode) ? "_parent_" : "_parent") + parentNode);
159
160 nodeChildren.add(childNode);
161
162
163 ++childIndex;
164 }
165 node.setChildren(nodeChildren);
166
167 return node;
168 }
169
170
171
172
173 private NodePrototype getNodePrototype(Node<Object, String> nodeData) {
174 NodePrototype result = null;
175 if (nodeData != null && nodeData.getData() != null) {
176 Class<?> dataClass = nodeData.getData().getClass();
177 result = nodePrototypeMap.get(dataClass);
178
179
180
181 if (result == null) {
182 for (Map.Entry<Class<?>, NodePrototype> prototypeEntry : nodePrototypeMap.entrySet()) {
183 if (prototypeEntry.getKey().isAssignableFrom(dataClass)) {
184 result = prototypeEntry.getValue();
185 break;
186 }
187 }
188 }
189 }
190
191 if (result == null) {
192 result = defaultNodePrototype;
193 }
194
195 return result;
196 }
197
198
199
200
201 @Override
202 public List<Component> getComponentsForLifecycle() {
203 List<Component> components = super.getComponentsForLifecycle();
204
205 components.add(tree);
206 addNodeComponents(treeGroups.getRootElement(), components);
207
208 return components;
209 }
210
211
212
213
214 @Override
215 public List<Component> getComponentPrototypes() {
216 List<Component> components = super.getComponentPrototypes();
217
218 if (defaultNodePrototype != null) {
219 components.add(defaultNodePrototype.getLabelPrototype());
220 components.add(defaultNodePrototype.getDataGroupPrototype());
221 }
222
223 if (nodePrototypeMap != null) {
224 for (Map.Entry<Class<?>, NodePrototype> prototypeEntry : nodePrototypeMap.entrySet()) {
225 NodePrototype prototype = prototypeEntry.getValue();
226 if (prototype != null) {
227 components.add(prototype.getLabelPrototype());
228 components.add(prototype.getDataGroupPrototype());
229 }
230 }
231 }
232
233 return components;
234 }
235
236
237
238
239
240
241
242
243 protected void addNodeComponents(Node<Group, Message> node, List<Component> components) {
244 if (node != null) {
245 components.add(node.getNodeLabel());
246 components.add(node.getData());
247
248 for (Node<Group, Message> nodeChild : node.getChildren()) {
249 addNodeComponents(nodeChild, components);
250 }
251 }
252 }
253
254 @BeanTagAttribute(name = "propertyName")
255 public String getPropertyName() {
256 return propertyName;
257 }
258
259 public void setPropertyName(String propertyName) {
260 this.propertyName = propertyName;
261 }
262
263 @BeanTagAttribute(name = "bindingInfo", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
264 public BindingInfo getBindingInfo() {
265 return bindingInfo;
266 }
267
268 public void setBindingInfo(BindingInfo bindingInfo) {
269 this.bindingInfo = bindingInfo;
270 }
271
272
273
274
275 @BeanTagAttribute(name = "defaultNodePrototype", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
276 public NodePrototype getDefaultNodePrototype() {
277 return this.defaultNodePrototype;
278 }
279
280
281
282
283 public void setDefaultNodePrototype(NodePrototype defaultNodePrototype) {
284 this.defaultNodePrototype = defaultNodePrototype;
285 }
286
287
288
289
290 @BeanTagAttribute(name = "NodePrototypeMap", type = BeanTagAttribute.AttributeType.MAPBEAN)
291 public Map<Class<?>, NodePrototype> getNodePrototypeMap() {
292 return this.nodePrototypeMap;
293 }
294
295
296
297
298 public void setNodePrototypeMap(Map<Class<?>, NodePrototype> nodePrototypeMap) {
299 this.nodePrototypeMap = nodePrototypeMap;
300 }
301
302 @BeanTagAttribute(name = "treeGroups", type = BeanTagAttribute.AttributeType.MAP2BEAN)
303 public Tree<Group, Message> getTreeGroups() {
304 return treeGroups;
305 }
306
307 public void setTreeGroups(Tree<Group, Message> treeGroups) {
308 this.treeGroups = treeGroups;
309 }
310
311 @BeanTagAttribute(name = "tree", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
312 public org.kuali.rice.krad.uif.widget.Tree getTree() {
313 return tree;
314 }
315
316 public void setTree(org.kuali.rice.krad.uif.widget.Tree tree) {
317 this.tree = tree;
318 }
319
320
321
322
323 @Override
324 protected <T> void copyProperties(T component) {
325 super.copyProperties(component);
326
327 TreeGroup treeGroupCopy = (TreeGroup) component;
328
329 treeGroupCopy.setPropertyName(this.propertyName);
330
331 if (this.bindingInfo != null) {
332 treeGroupCopy.setBindingInfo((BindingInfo) this.bindingInfo.copy());
333 }
334
335 if (this.defaultNodePrototype != null) {
336 treeGroupCopy.setDefaultNodePrototype((NodePrototype) this.defaultNodePrototype.copy());
337 }
338
339 if (this.treeGroups != null) {
340 Tree<Group, Message> treeGroupsCopy = new Tree<Group, Message>();
341 treeGroupsCopy.setRootElement(copyNode(this.treeGroups.getRootElement()));
342
343 treeGroupCopy.setTreeGroups(treeGroupsCopy);
344 }
345
346 if (this.tree != null) {
347 treeGroupCopy.setTree((org.kuali.rice.krad.uif.widget.Tree) this.tree.copy());
348 }
349
350 if (this.nodePrototypeMap != null) {
351 Map<Class<?>, NodePrototype> nodePrototypeMapCopy = new HashMap<Class<?>, NodePrototype>();
352 for (Map.Entry<Class<?>, NodePrototype> nodePrototypeMapEntry : nodePrototypeMap.entrySet()) {
353 NodePrototype prototypeCopy = nodePrototypeMapEntry.getValue().copy();
354 nodePrototypeMapCopy.put(nodePrototypeMapEntry.getKey(), prototypeCopy);
355 }
356
357 treeGroupCopy.setNodePrototypeMap(nodePrototypeMapCopy);
358 }
359 }
360
361
362
363
364
365
366
367 protected Node<Group, Message> copyNode(Node<Group, Message> node) {
368 Node<Group, Message> nodeCopy = new Node<Group, Message>();
369
370 if (node == null) {
371 return null;
372 }
373
374 if (node.getData() != null) {
375 nodeCopy.setData((Group) node.getData().copy());
376 }
377
378 if (node.getNodeLabel() != null) {
379 nodeCopy.setNodeLabel((Message) node.getNodeLabel().copy());
380 }
381
382 if (node.getChildren() != null) {
383 List<Node<Group, Message>> childrenCopy = new ArrayList<Node<Group, Message>>();
384 for (Node<Group, Message> childNode : node.getChildren()) {
385 childrenCopy.add(copyNode(childNode));
386 }
387
388 nodeCopy.setChildren(childrenCopy);
389 }
390
391 return nodeCopy;
392 }
393 }