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