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.CollectionGroup;
22 import org.kuali.rice.krad.uif.container.Container;
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.component.Ordered;
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.layout.LayoutManager;
29 import org.kuali.rice.krad.util.ObjectUtils;
30 import org.springframework.beans.BeanUtils;
31 import org.springframework.core.OrderComparator;
32
33 import java.beans.PropertyDescriptor;
34 import java.io.Serializable;
35 import java.util.ArrayList;
36 import java.util.Collections;
37 import java.util.HashSet;
38 import java.util.List;
39 import java.util.Set;
40
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 public static <T extends Component> List<T> getComponentsOfTypeDeep(List<? extends Component> items,
172 Class<T> componentType) {
173 List<T> typeComponents = new ArrayList<T>();
174
175 for (Component component : items) {
176 typeComponents.addAll(getComponentsOfTypeDeep(component, componentType));
177 }
178
179 return typeComponents;
180 }
181
182 @SuppressWarnings("unchecked")
183 public static <T extends Component> List<T> getComponentsOfTypeDeep(Component component, Class<T> componentType) {
184 List<T> typeComponents = new ArrayList<T>();
185
186 if (component == null) {
187 return typeComponents;
188 }
189
190 if (componentType.isAssignableFrom(component.getClass())) {
191 typeComponents.add((T) component);
192 }
193
194 for (Component nested : component.getComponentsForLifecycle()) {
195 typeComponents.addAll(getComponentsOfTypeDeep(nested, componentType));
196 }
197
198 return typeComponents;
199 }
200
201 public static List<Component> getAllNestedComponents(Component component) {
202 List<Component> components = new ArrayList<Component>();
203
204 if (component == null) {
205 return components;
206 }
207
208 for (Component nested : component.getComponentsForLifecycle()) {
209 components.add(nested);
210 components.addAll(getAllNestedComponents(nested));
211 }
212
213 return components;
214 }
215
216 public static void prefixBindingPath(List<? extends Field> fields, String addBindingPrefix) {
217 for (Field field : fields) {
218 if (field instanceof DataBinding) {
219 prefixBindingPath((DataBinding) field, addBindingPrefix);
220 }
221 else if ((field instanceof FieldGroup) && (((FieldGroup) field).getItems() != null) ) {
222 List<Field> groupFields = getComponentsOfType(((FieldGroup) field).getItems(), Field.class);
223 prefixBindingPath(groupFields, addBindingPrefix);
224 }
225 }
226 }
227
228 public static void prefixBindingPathNested(Component component, String addBindingPrefix) {
229 if (component instanceof DataBinding) {
230 if (LOG.isDebugEnabled()) {
231 LOG.info("setting nested binding prefix '"+ addBindingPrefix +"' on " + component);
232 }
233 prefixBindingPath((DataBinding) component, addBindingPrefix);
234 }
235
236 for (Component nested : component.getComponentsForLifecycle()) {
237 if (nested != null) {
238 prefixBindingPathNested(nested, addBindingPrefix);
239 }
240 }
241 }
242
243 public static void prefixBindingPath(DataBinding field, String addBindingPrefix) {
244 String bindingPrefix = addBindingPrefix;
245 if (StringUtils.isNotBlank(field.getBindingInfo().getBindByNamePrefix())) {
246 bindingPrefix += "." + field.getBindingInfo().getBindByNamePrefix();
247 }
248 field.getBindingInfo().setBindByNamePrefix(bindingPrefix);
249 }
250
251 public static void updateIdsWithSuffixNested(List<? extends Component> components, String idSuffix) {
252 for (Component component : components) {
253 updateIdsWithSuffixNested(component, idSuffix);
254 }
255 }
256
257 public static void updateIdsWithSuffixNested(Component component, String idSuffix) {
258 updateIdsWithSuffix(component, idSuffix);
259
260 if (Container.class.isAssignableFrom(component.getClass())) {
261 LayoutManager layoutManager = ((Container) component).getLayoutManager();
262 layoutManager.setId(layoutManager.getId() + idSuffix);
263 }
264
265 for (Component nested : component.getComponentsForLifecycle()) {
266 if (nested != null) {
267 updateIdsWithSuffixNested(nested, idSuffix);
268 }
269 }
270
271 for (Component nested : component.getPropertyReplacerComponents()) {
272 if (nested != null) {
273 updateIdsWithSuffixNested(nested, idSuffix);
274 }
275 }
276 }
277
278 public static void updateIdsWithSuffix(Component component, String idSuffix) {
279 component.setId(component.getId() + idSuffix);
280 }
281
282 public static void setComponentsPropertyDeep(List<? extends Component> components, String propertyPath,
283 Object propertyValue) {
284 for (Component component : components) {
285 setComponentPropertyDeep(component, propertyPath, propertyValue);
286 }
287 }
288
289 public static void setComponentPropertyDeep(Component component, String propertyPath, Object propertyValue) {
290 ObjectPropertyUtils.setPropertyValue(component, propertyPath, propertyValue, true);
291
292 for (Component nested : component.getComponentsForLifecycle()) {
293 if (nested != null) {
294 setComponentPropertyDeep(nested, propertyPath, propertyValue);
295 }
296 }
297 }
298
299 public static List<String> getComponentPropertyNames(Class<? extends Component> componentClass) {
300 List<String> componentProperties = new ArrayList<String>();
301
302 PropertyDescriptor[] properties = BeanUtils.getPropertyDescriptors(componentClass);
303 for (int i = 0; i < properties.length; i++) {
304 PropertyDescriptor descriptor = properties[i];
305 if (descriptor.getReadMethod() != null) {
306 componentProperties.add(descriptor.getName());
307 }
308 }
309
310 return componentProperties;
311 }
312
313 public static void pushObjectToContext(List<? extends Component> components, String contextName, Object contextValue) {
314 for (Component component : components) {
315 pushObjectToContext(component, contextName, contextValue);
316 }
317 }
318
319 public static void pushObjectToContext(Component component, String contextName, Object contextValue) {
320 if (component == null) {
321 return;
322 }
323
324 component.pushObjectToContext(contextName, contextValue);
325
326
327 if (Container.class.isAssignableFrom(component.getClass())) {
328 LayoutManager layoutManager = ((Container) component).getLayoutManager();
329 if (layoutManager != null) {
330 layoutManager.pushObjectToContext(contextName, contextValue);
331
332 for (Component nestedComponent : layoutManager.getComponentsForLifecycle()) {
333 pushObjectToContext(nestedComponent, contextName, contextValue);
334 }
335 }
336 }
337
338 for (Component nestedComponent : component.getComponentsForLifecycle()) {
339 pushObjectToContext(nestedComponent, contextName, contextValue);
340 }
341 }
342
343 public static void updateContextsForLine(List<? extends Component> components, Object collectionLine,
344 int lineIndex) {
345 for (Component component : components) {
346 updateContextForLine(component, collectionLine, lineIndex);
347 }
348 }
349
350 public static void updateContextForLine(Component component, Object collectionLine, int lineIndex) {
351 pushObjectToContext(component, UifConstants.ContextVariableNames.LINE, collectionLine);
352 pushObjectToContext(component, UifConstants.ContextVariableNames.INDEX, new Integer(lineIndex));
353
354 boolean isAddLine = (lineIndex == -1);
355 pushObjectToContext(component, UifConstants.ContextVariableNames.IS_ADD_LINE, isAddLine);
356 }
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377 public static List<? extends Ordered> sort(List<? extends Ordered> items, int defaultOrderSequence) {
378 List<Ordered> orderedItems = new ArrayList<Ordered>();
379
380
381 Set<Integer> foundOrders = new HashSet<Integer>();
382
383
384 Collections.reverse(items);
385 for (Ordered component : items) {
386 int order = component.getOrder();
387
388
389 if (order == 0) {
390 orderedItems.add(component);
391 }
392
393 else if (!foundOrders.contains(new Integer(order))) {
394 orderedItems.add(component);
395 foundOrders.add(new Integer(order));
396 }
397 }
398
399
400
401 Collections.reverse(items);
402 for (Ordered component : items) {
403 int order = component.getOrder();
404
405
406 if (order == 0) {
407 defaultOrderSequence++;
408 while (foundOrders.contains(new Integer(defaultOrderSequence))) {
409 defaultOrderSequence++;
410 }
411 component.setOrder(defaultOrderSequence);
412 }
413 }
414
415
416 Collections.sort(orderedItems, new OrderComparator());
417
418 return orderedItems;
419 }
420
421 public static String getLinePathValue(Component component) {
422 CollectionGroup collectionGroup =
423 (CollectionGroup) (component.getContext().get(UifConstants.ContextVariableNames.COLLECTION_GROUP));
424 String linePath = "";
425 if (collectionGroup != null) {
426 Object indexObj = component.getContext().get(UifConstants.ContextVariableNames.INDEX);
427 if (indexObj != null) {
428 int index = (Integer) indexObj;
429 boolean addLine = false;
430 Object addLineObj = component.getContext().get(UifConstants.ContextVariableNames.IS_ADD_LINE);
431
432 if (addLineObj != null) {
433 addLine = (Boolean) addLineObj;
434 }
435 if (addLine) {
436 linePath = collectionGroup.getAddLineBindingInfo().getBindingPath();
437 } else {
438 linePath = collectionGroup.getBindingInfo().getBindingPath() + "[" + index + "]";
439 }
440 }
441 }
442 return linePath;
443 }
444
445 public static String replaceLineAttr(String statement, String replacement){
446 if (statement.contains("#line") && StringUtils.isNotEmpty(replacement)) {
447 statement = statement.replace("#line?", replacement);
448 statement = statement.replace("#line", replacement);
449 }
450 return statement;
451 }
452 }