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