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