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