1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.uif.util;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.kuali.rice.core.api.util.type.TypeUtils;
20 import org.kuali.rice.krad.uif.UifConstants;
21 import org.kuali.rice.krad.uif.container.Container;
22 import org.kuali.rice.krad.uif.component.Component;
23 import org.kuali.rice.krad.uif.component.DataBinding;
24 import org.kuali.rice.krad.uif.component.Ordered;
25 import org.kuali.rice.krad.uif.container.ContainerBase;
26 import org.kuali.rice.krad.uif.field.Field;
27 import org.kuali.rice.krad.uif.field.FieldGroup;
28 import org.kuali.rice.krad.uif.field.InputField;
29 import org.kuali.rice.krad.uif.layout.LayoutManager;
30 import org.kuali.rice.krad.util.ObjectUtils;
31 import org.springframework.beans.BeanUtils;
32 import org.springframework.core.OrderComparator;
33
34 import java.beans.PropertyDescriptor;
35 import java.io.Serializable;
36 import java.util.ArrayList;
37 import java.util.Collections;
38 import java.util.HashSet;
39 import java.util.List;
40 import java.util.Set;
41
42
43
44
45
46
47 public class ComponentUtils {
48 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ComponentUtils.class);
49
50
51 public static <T extends Component> T copy(T component) {
52 return copy(component, null);
53 }
54
55 public static <T extends Component> T copy(T component, String idSuffix) {
56 T copy = copyObject(component);
57
58 if (StringUtils.isNotBlank(idSuffix)) {
59 updateIdsWithSuffixNested(copy, idSuffix);
60 }
61
62 return copy;
63 }
64
65 public static <T extends Object> T copyObject(T object) {
66 if (object == null) {
67 return null;
68 }
69
70 T copy = null;
71 try {
72 copy = CloneUtils.deepClone(object);
73 }
74 catch (Exception e) {
75 throw new RuntimeException(e);
76 }
77
78 return copy;
79 }
80
81 protected static Object getCopyPropertyValue(Set<String> propertiesForReferenceCopy, String propertyName,
82 Object propertyValue) {
83 if (propertyValue == null) {
84 return null;
85 }
86
87 Object copyValue = propertyValue;
88
89 Class<?> valuePropertyType = propertyValue.getClass();
90 if (propertiesForReferenceCopy.contains(propertyName) || TypeUtils.isSimpleType(valuePropertyType)
91 || TypeUtils.isClassClass(valuePropertyType)) {
92 return copyValue;
93 }
94
95 if (Component.class.isAssignableFrom(valuePropertyType)
96 || LayoutManager.class.isAssignableFrom(valuePropertyType)) {
97 copyValue = copyObject(propertyValue);
98 }
99 else {
100 copyValue = ObjectUtils.deepCopy((Serializable) propertyValue);
101 }
102
103 return copyValue;
104 }
105
106 @SuppressWarnings("unchecked")
107 protected static <T extends Object> T getNewInstance(T object) {
108 T copy = null;
109 try {
110 copy = (T) object.getClass().newInstance();
111 }
112 catch (Exception e) {
113 throw new RuntimeException("Unable to create new instance of class: " + object.getClass());
114 }
115
116 return copy;
117 }
118
119 public static <T extends Field> List<T> copyFieldList(List<T> fields, String addBindingPrefix, String idSuffix) {
120 List<T> copiedFieldList = copyFieldList(fields, idSuffix);
121
122 prefixBindingPath(copiedFieldList, addBindingPrefix);
123
124 return copiedFieldList;
125 }
126
127 public static <T extends Field> List<T> copyFieldList(List<T> fields, String idSuffix) {
128 List<T> copiedFieldList = new ArrayList<T>();
129
130 for (T field : fields) {
131 T copiedField = copy(field, idSuffix);
132 copiedFieldList.add(copiedField);
133 }
134
135 return copiedFieldList;
136 }
137
138 public static <T extends Component> T copyComponent(T component, String addBindingPrefix, String idSuffix) {
139 T copy = copy(component, idSuffix);
140
141 prefixBindingPathNested(copy, addBindingPrefix);
142
143 return copy;
144 }
145
146 public static <T extends Component> List<T> copyComponentList(List<T> components, String idSuffix) {
147 List<T> copiedComponentList = new ArrayList<T>();
148
149 for (T field : components) {
150 T copiedComponent = copy(field, idSuffix);
151 copiedComponentList.add(copiedComponent);
152 }
153
154 return copiedComponentList;
155 }
156
157 @SuppressWarnings("unchecked")
158 public static <T extends Component> List<T> getComponentsOfType(List<? extends Component> items,
159 Class<T> componentType) {
160 List<T> typeComponents = new ArrayList<T>();
161
162 for (Component component : items) {
163 if (componentType.isAssignableFrom(component.getClass())) {
164 typeComponents.add((T) component);
165 }
166 }
167
168 return typeComponents;
169 }
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185 public static <T extends Component> List<T> getComponentsOfTypeDeep(List<? extends Component> items,
186 Class<T> componentType) {
187 List<T> typeComponents = new ArrayList<T>();
188
189 for (Component component : items) {
190 typeComponents.addAll(getComponentsOfTypeDeep(component, componentType));
191 }
192
193 return typeComponents;
194 }
195
196 @SuppressWarnings("unchecked")
197 public static <T extends Component> List<T> getComponentsOfTypeDeep(Component component, Class<T> componentType) {
198 List<T> typeComponents = new ArrayList<T>();
199
200 if (component == null) {
201 return typeComponents;
202 }
203
204 if (componentType.isAssignableFrom(component.getClass())) {
205 typeComponents.add((T) component);
206 }
207
208 for (Component nested : component.getComponentsForLifecycle()) {
209 typeComponents.addAll(getComponentsOfTypeDeep(nested, componentType));
210 }
211
212 return typeComponents;
213 }
214
215 public static List<Component> getAllNestedComponents(Component component) {
216 List<Component> components = new ArrayList<Component>();
217
218 if (component == null) {
219 return components;
220 }
221
222 for (Component nested : component.getComponentsForLifecycle()) {
223 if (nested != null) {
224 components.add(nested);
225 components.addAll(getAllNestedComponents(nested));
226 }
227 }
228
229 return components;
230 }
231
232
233
234
235
236
237
238
239 public static Component findNestedComponentById(Component parent, String nestedId) {
240 Component childComponent = null;
241
242 List<Component> children = getAllNestedComponents(parent);
243 for (Component child : children) {
244 if (StringUtils.equals(nestedId, child.getId())) {
245 childComponent = child;
246 break;
247 }
248 }
249
250 return childComponent;
251 }
252
253 public static void prefixBindingPath(List<? extends Field> fields, String addBindingPrefix) {
254 for (Field field : fields) {
255 if (field instanceof DataBinding) {
256 prefixBindingPath((DataBinding) field, addBindingPrefix);
257 }
258 else if ((field instanceof FieldGroup) && (((FieldGroup) field).getItems() != null) ) {
259 List<Field> groupFields = getComponentsOfTypeDeep(((FieldGroup) field).getItems(), Field.class);
260 prefixBindingPath(groupFields, addBindingPrefix);
261 }
262 }
263 }
264
265 public static void prefixBindingPathNested(Component component, String addBindingPrefix) {
266 if (component instanceof DataBinding) {
267 if (LOG.isDebugEnabled()) {
268 LOG.info("setting nested binding prefix '"+ addBindingPrefix +"' on " + component);
269 }
270 prefixBindingPath((DataBinding) component, addBindingPrefix);
271 }
272
273 for (Component nested : component.getComponentsForLifecycle()) {
274 if (nested != null) {
275 prefixBindingPathNested(nested, addBindingPrefix);
276 }
277 }
278 }
279
280 public static void prefixBindingPath(DataBinding field, String addBindingPrefix) {
281 String bindingPrefix = addBindingPrefix;
282 if (StringUtils.isNotBlank(field.getBindingInfo().getBindByNamePrefix())) {
283 bindingPrefix += "." + field.getBindingInfo().getBindByNamePrefix();
284 }
285 field.getBindingInfo().setBindByNamePrefix(bindingPrefix);
286 }
287
288 public static void updateIdsWithSuffixNested(List<? extends Component> components, String idSuffix) {
289 for (Component component : components) {
290 updateIdsWithSuffixNested(component, idSuffix);
291 }
292 }
293
294 public static void updateIdsWithSuffixNested(Component component, String idSuffix) {
295 updateIdWithSuffix(component, idSuffix);
296
297
298 if (Container.class.isAssignableFrom(component.getClass())) {
299 LayoutManager layoutManager = ((Container) component).getLayoutManager();
300 layoutManager.setId(layoutManager.getId() + idSuffix);
301 }
302
303 for (Component nested : component.getComponentsForLifecycle()) {
304 if (nested != null) {
305 updateIdsWithSuffixNested(nested, idSuffix);
306 }
307 }
308
309 for (Component nested : component.getPropertyReplacerComponents()) {
310 if (nested != null) {
311 updateIdsWithSuffixNested(nested, idSuffix);
312 }
313 }
314 }
315
316
317
318
319
320
321
322 public static void updateIdWithSuffix(Component component, String idSuffix) {
323 if (component != null && !StringUtils.isEmpty(idSuffix)) {
324 component.setId(component.getId() + idSuffix);
325 }
326 }
327
328 public static void setComponentsPropertyDeep(List<? extends Component> components, String propertyPath,
329 Object propertyValue) {
330 for (Component component : components) {
331 setComponentPropertyDeep(component, propertyPath, propertyValue);
332 }
333 }
334
335 public static void setComponentPropertyDeep(Component component, String propertyPath, Object propertyValue) {
336 ObjectPropertyUtils.setPropertyValue(component, propertyPath, propertyValue, true);
337
338 for (Component nested : component.getComponentsForLifecycle()) {
339 if (nested != null) {
340 setComponentPropertyDeep(nested, propertyPath, propertyValue);
341 }
342 }
343 }
344
345 public static List<String> getComponentPropertyNames(Class<? extends Component> componentClass) {
346 List<String> componentProperties = new ArrayList<String>();
347
348 PropertyDescriptor[] properties = BeanUtils.getPropertyDescriptors(componentClass);
349 for (int i = 0; i < properties.length; i++) {
350 PropertyDescriptor descriptor = properties[i];
351 if (descriptor.getReadMethod() != null) {
352 componentProperties.add(descriptor.getName());
353 }
354 }
355
356 return componentProperties;
357 }
358
359
360
361
362
363
364
365
366 public static void pushObjectToContext(List<? extends Component> components, String contextName, Object contextValue) {
367 for (Component component : components) {
368 pushObjectToContext(component, contextName, contextValue);
369 }
370 }
371
372
373
374
375
376
377
378
379
380
381
382 public static void pushObjectToContext(Component component, String contextName, Object contextValue) {
383 if (component == null) {
384 return;
385 }
386
387 component.pushObjectToContext(contextName, contextValue);
388
389
390 if (Container.class.isAssignableFrom(component.getClass())) {
391 LayoutManager layoutManager = ((Container) component).getLayoutManager();
392 if (layoutManager != null) {
393
394 if (layoutManager.getContext().get(contextName) != contextValue) {
395 layoutManager.pushObjectToContext(contextName, contextValue);
396
397 for (Component nestedComponent : layoutManager.getComponentsForLifecycle()) {
398 pushObjectToContext(nestedComponent, contextName, contextValue);
399 }
400 }
401 }
402 }
403
404 for (Component nestedComponent : component.getComponentsForLifecycle()) {
405 pushObjectToContext(nestedComponent, contextName, contextValue);
406 }
407 }
408
409
410
411
412
413
414
415
416
417
418 public static void updateContextsForLine(List<? extends Component> components, Object collectionLine,
419 int lineIndex) {
420 for (Component component : components) {
421 updateContextForLine(component, collectionLine, lineIndex);
422 }
423 }
424
425
426
427
428
429
430
431
432
433
434
435 public static void updateContextForLine(Component component, Object collectionLine, int lineIndex) {
436 pushObjectToContext(component, UifConstants.ContextVariableNames.LINE, collectionLine);
437 pushObjectToContext(component, UifConstants.ContextVariableNames.INDEX, Integer.valueOf(lineIndex));
438
439 boolean isAddLine = (lineIndex == -1);
440 pushObjectToContext(component, UifConstants.ContextVariableNames.IS_ADD_LINE, isAddLine);
441 }
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462 public static List<? extends Ordered> sort(List<? extends Ordered> items, int defaultOrderSequence) {
463 List<Ordered> orderedItems = new ArrayList<Ordered>();
464
465
466 Set<Integer> foundOrders = new HashSet<Integer>();
467
468
469 Collections.reverse(items);
470 for (Ordered component : items) {
471 int order = component.getOrder();
472
473
474 if (order == 0) {
475 orderedItems.add(component);
476 }
477
478 else if (!foundOrders.contains(Integer.valueOf(order))) {
479 orderedItems.add(component);
480 foundOrders.add(Integer.valueOf(order));
481 }
482 }
483
484
485
486 Collections.reverse(items);
487 for (Ordered component : items) {
488 int order = component.getOrder();
489
490
491 if (order == 0) {
492 defaultOrderSequence++;
493 while (foundOrders.contains(Integer.valueOf(defaultOrderSequence))) {
494 defaultOrderSequence++;
495 }
496 component.setOrder(defaultOrderSequence);
497 }
498 }
499
500
501 Collections.sort(orderedItems, new OrderComparator());
502
503 return orderedItems;
504 }
505
506
507
508
509
510
511
512
513 public static List<InputField> getAllInputFieldsWithinContainer(Container container) {
514 List<InputField> inputFields = new ArrayList<InputField>();
515
516 for (Component c : container.getComponentsForLifecycle()) {
517 if (c instanceof InputField) {
518 inputFields.add((InputField) c);
519 } else if (c instanceof Container) {
520 inputFields.addAll(getAllInputFieldsWithinContainer((Container) c));
521 } else if (c instanceof FieldGroup) {
522 Container cb = ((FieldGroup) c).getGroup();
523
524 inputFields.addAll(getAllInputFieldsWithinContainer(cb));
525 }
526 }
527
528 return inputFields;
529 }
530
531 }