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