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.field.Field;
26 import org.kuali.rice.krad.uif.field.FieldGroup;
27 import org.kuali.rice.krad.uif.layout.LayoutManager;
28 import org.kuali.rice.krad.util.ObjectUtils;
29 import org.springframework.beans.BeanUtils;
30 import org.springframework.core.OrderComparator;
31
32 import java.beans.PropertyDescriptor;
33 import java.io.Serializable;
34 import java.util.ArrayList;
35 import java.util.Collections;
36 import java.util.HashSet;
37 import java.util.List;
38 import java.util.Set;
39
40
41
42
43
44
45
46 public class ComponentUtils {
47 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ComponentUtils.class);
48
49
50 public static <T extends Component> T copy(T component) {
51 return copy(component, null);
52 }
53
54 public static <T extends Component> T copy(T component, String idSuffix) {
55 T copy = copyObject(component);
56
57 if (StringUtils.isNotBlank(idSuffix)) {
58 updateIdsWithSuffixNested(copy, idSuffix);
59 }
60
61 return copy;
62 }
63
64 public static <T extends Object> T copyObject(T object) {
65 if (object == null) {
66 return null;
67 }
68
69 T copy = null;
70 try {
71 copy = CloneUtils.deepClone(object);
72 }
73 catch (Exception e) {
74 throw new RuntimeException(e);
75 }
76
77 return copy;
78 }
79
80 protected static Object getCopyPropertyValue(Set<String> propertiesForReferenceCopy, String propertyName,
81 Object propertyValue) {
82 if (propertyValue == null) {
83 return null;
84 }
85
86 Object copyValue = propertyValue;
87
88 Class<?> valuePropertyType = propertyValue.getClass();
89 if (propertiesForReferenceCopy.contains(propertyName) || TypeUtils.isSimpleType(valuePropertyType)
90 || TypeUtils.isClassClass(valuePropertyType)) {
91 return copyValue;
92 }
93
94 if (Component.class.isAssignableFrom(valuePropertyType)
95 || LayoutManager.class.isAssignableFrom(valuePropertyType)) {
96 copyValue = copyObject(propertyValue);
97 }
98 else {
99 copyValue = ObjectUtils.deepCopy((Serializable) propertyValue);
100 }
101
102 return copyValue;
103 }
104
105 @SuppressWarnings("unchecked")
106 protected static <T extends Object> T getNewInstance(T object) {
107 T copy = null;
108 try {
109 copy = (T) object.getClass().newInstance();
110 }
111 catch (Exception e) {
112 throw new RuntimeException("Unable to create new instance of class: " + object.getClass());
113 }
114
115 return copy;
116 }
117
118 public static <T extends Field> List<T> copyFieldList(List<T> fields, String addBindingPrefix, String idSuffix) {
119 List<T> copiedFieldList = copyFieldList(fields, idSuffix);
120
121 prefixBindingPath(copiedFieldList, addBindingPrefix);
122
123 return copiedFieldList;
124 }
125
126 public static <T extends Field> List<T> copyFieldList(List<T> fields, String idSuffix) {
127 List<T> copiedFieldList = new ArrayList<T>();
128
129 for (T field : fields) {
130 T copiedField = copy(field, idSuffix);
131 copiedFieldList.add(copiedField);
132 }
133
134 return copiedFieldList;
135 }
136
137 public static <T extends Component> T copyComponent(T component, String addBindingPrefix, String idSuffix) {
138 T copy = copy(component, idSuffix);
139
140 prefixBindingPathNested(copy, addBindingPrefix);
141
142 return copy;
143 }
144
145 public static <T extends Component> List<T> copyComponentList(List<T> components, String idSuffix) {
146 List<T> copiedComponentList = new ArrayList<T>();
147
148 for (T field : components) {
149 T copiedComponent = copy(field, idSuffix);
150 copiedComponentList.add(copiedComponent);
151 }
152
153 return copiedComponentList;
154 }
155
156 @SuppressWarnings("unchecked")
157 public static <T extends Component> List<T> getComponentsOfType(List<? extends Component> items,
158 Class<T> componentType) {
159 List<T> typeComponents = new ArrayList<T>();
160
161 for (Component component : items) {
162 if (componentType.isAssignableFrom(component.getClass())) {
163 typeComponents.add((T) component);
164 }
165 }
166
167 return typeComponents;
168 }
169
170 public static <T extends Component> List<T> getComponentsOfTypeDeep(List<? extends Component> items,
171 Class<T> componentType) {
172 List<T> typeComponents = new ArrayList<T>();
173
174 for (Component component : items) {
175 typeComponents.addAll(getComponentsOfTypeDeep(component, componentType));
176 }
177
178 return typeComponents;
179 }
180
181 @SuppressWarnings("unchecked")
182 public static <T extends Component> List<T> getComponentsOfTypeDeep(Component component, Class<T> componentType) {
183 List<T> typeComponents = new ArrayList<T>();
184
185 if (component == null) {
186 return typeComponents;
187 }
188
189 if (componentType.isAssignableFrom(component.getClass())) {
190 typeComponents.add((T) component);
191 }
192
193 for (Component nested : component.getComponentsForLifecycle()) {
194 typeComponents.addAll(getComponentsOfTypeDeep(nested, componentType));
195 }
196
197 return typeComponents;
198 }
199
200 public static List<Component> getAllNestedComponents(Component component) {
201 List<Component> components = new ArrayList<Component>();
202
203 if (component == null) {
204 return components;
205 }
206
207 for (Component nested : component.getComponentsForLifecycle()) {
208 if (nested != null) {
209 components.add(nested);
210 components.addAll(getAllNestedComponents(nested));
211 }
212 }
213
214 return components;
215 }
216
217 public static void prefixBindingPath(List<? extends Field> fields, String addBindingPrefix) {
218 for (Field field : fields) {
219 if (field instanceof DataBinding) {
220 prefixBindingPath((DataBinding) field, addBindingPrefix);
221 }
222 else if ((field instanceof FieldGroup) && (((FieldGroup) field).getItems() != null) ) {
223 List<Field> groupFields = getComponentsOfType(((FieldGroup) field).getItems(), Field.class);
224 prefixBindingPath(groupFields, addBindingPrefix);
225 }
226 }
227 }
228
229 public static void prefixBindingPathNested(Component component, String addBindingPrefix) {
230 if (component instanceof DataBinding) {
231 if (LOG.isDebugEnabled()) {
232 LOG.info("setting nested binding prefix '"+ addBindingPrefix +"' on " + component);
233 }
234 prefixBindingPath((DataBinding) component, addBindingPrefix);
235 }
236
237 for (Component nested : component.getComponentsForLifecycle()) {
238 if (nested != null) {
239 prefixBindingPathNested(nested, addBindingPrefix);
240 }
241 }
242 }
243
244 public static void prefixBindingPath(DataBinding field, String addBindingPrefix) {
245 String bindingPrefix = addBindingPrefix;
246 if (StringUtils.isNotBlank(field.getBindingInfo().getBindByNamePrefix())) {
247 bindingPrefix += "." + field.getBindingInfo().getBindByNamePrefix();
248 }
249 field.getBindingInfo().setBindByNamePrefix(bindingPrefix);
250 }
251
252 public static void updateIdsWithSuffixNested(List<? extends Component> components, String idSuffix) {
253 for (Component component : components) {
254 updateIdsWithSuffixNested(component, idSuffix);
255 }
256 }
257
258 public static void updateIdsWithSuffixNested(Component component, String idSuffix) {
259 updateIdWithSuffix(component, idSuffix);
260
261 if (Container.class.isAssignableFrom(component.getClass())) {
262 LayoutManager layoutManager = ((Container) component).getLayoutManager();
263 layoutManager.setId(layoutManager.getId() + idSuffix);
264 }
265
266 for (Component nested : component.getComponentsForLifecycle()) {
267 if (nested != null) {
268 updateIdsWithSuffixNested(nested, idSuffix);
269 }
270 }
271
272 for (Component nested : component.getPropertyReplacerComponents()) {
273 if (nested != null) {
274 updateIdsWithSuffixNested(nested, idSuffix);
275 }
276 }
277 }
278
279 public static void updateIdWithSuffix(Component component, String idSuffix) {
280 component.setId(component.getId() + idSuffix);
281 }
282
283 public static void setComponentsPropertyDeep(List<? extends Component> components, String propertyPath,
284 Object propertyValue) {
285 for (Component component : components) {
286 setComponentPropertyDeep(component, propertyPath, propertyValue);
287 }
288 }
289
290 public static void setComponentPropertyDeep(Component component, String propertyPath, Object propertyValue) {
291 ObjectPropertyUtils.setPropertyValue(component, propertyPath, propertyValue, true);
292
293 for (Component nested : component.getComponentsForLifecycle()) {
294 if (nested != null) {
295 setComponentPropertyDeep(nested, propertyPath, propertyValue);
296 }
297 }
298 }
299
300 public static List<String> getComponentPropertyNames(Class<? extends Component> componentClass) {
301 List<String> componentProperties = new ArrayList<String>();
302
303 PropertyDescriptor[] properties = BeanUtils.getPropertyDescriptors(componentClass);
304 for (int i = 0; i < properties.length; i++) {
305 PropertyDescriptor descriptor = properties[i];
306 if (descriptor.getReadMethod() != null) {
307 componentProperties.add(descriptor.getName());
308 }
309 }
310
311 return componentProperties;
312 }
313
314 public static void pushObjectToContext(List<? extends Component> components, String contextName, Object contextValue) {
315 for (Component component : components) {
316 pushObjectToContext(component, contextName, contextValue);
317 }
318 }
319
320 public static void pushObjectToContext(Component component, String contextName, Object contextValue) {
321 if (component == null) {
322 return;
323 }
324
325 component.pushObjectToContext(contextName, contextValue);
326
327
328 if (Container.class.isAssignableFrom(component.getClass())) {
329 LayoutManager layoutManager = ((Container) component).getLayoutManager();
330 if (layoutManager != null) {
331 layoutManager.pushObjectToContext(contextName, contextValue);
332
333 for (Component nestedComponent : layoutManager.getComponentsForLifecycle()) {
334 pushObjectToContext(nestedComponent, contextName, contextValue);
335 }
336 }
337 }
338
339 for (Component nestedComponent : component.getComponentsForLifecycle()) {
340 pushObjectToContext(nestedComponent, contextName, contextValue);
341 }
342 }
343
344 public static void updateContextsForLine(List<? extends Component> components, Object collectionLine,
345 int lineIndex) {
346 for (Component component : components) {
347 updateContextForLine(component, collectionLine, lineIndex);
348 }
349 }
350
351 public static void updateContextForLine(Component component, Object collectionLine, int lineIndex) {
352 pushObjectToContext(component, UifConstants.ContextVariableNames.LINE, collectionLine);
353 pushObjectToContext(component, UifConstants.ContextVariableNames.INDEX, new Integer(lineIndex));
354
355 boolean isAddLine = (lineIndex == -1);
356 pushObjectToContext(component, UifConstants.ContextVariableNames.IS_ADD_LINE, isAddLine);
357 }
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378 public static List<? extends Ordered> sort(List<? extends Ordered> items, int defaultOrderSequence) {
379 List<Ordered> orderedItems = new ArrayList<Ordered>();
380
381
382 Set<Integer> foundOrders = new HashSet<Integer>();
383
384
385 Collections.reverse(items);
386 for (Ordered component : items) {
387 int order = component.getOrder();
388
389
390 if (order == 0) {
391 orderedItems.add(component);
392 }
393
394 else if (!foundOrders.contains(new Integer(order))) {
395 orderedItems.add(component);
396 foundOrders.add(new Integer(order));
397 }
398 }
399
400
401
402 Collections.reverse(items);
403 for (Ordered component : items) {
404 int order = component.getOrder();
405
406
407 if (order == 0) {
408 defaultOrderSequence++;
409 while (foundOrders.contains(new Integer(defaultOrderSequence))) {
410 defaultOrderSequence++;
411 }
412 component.setOrder(defaultOrderSequence);
413 }
414 }
415
416
417 Collections.sort(orderedItems, new OrderComparator());
418
419 return orderedItems;
420 }
421
422 }