Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
Formatter |
|
| 5.193548387096774;5.194 | ||||
Formatter$ArrayUtils |
|
| 5.193548387096774;5.194 |
1 | /* | |
2 | * Copyright 2006-2011 The Kuali Foundation | |
3 | * | |
4 | * Licensed under the Educational Community License, Version 2.0 (the "License"); | |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at | |
7 | * | |
8 | * http://www.opensource.org/licenses/ecl2.php | |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
15 | */ | |
16 | // begin Kuali Foundation modification | |
17 | package org.kuali.rice.core.web.format; | |
18 | // end Kuali Foundation modification | |
19 | ||
20 | import org.apache.commons.beanutils.PropertyUtils; | |
21 | import org.apache.commons.lang.StringUtils; | |
22 | import org.kuali.rice.core.util.type.AbstractKualiDecimal; | |
23 | import org.kuali.rice.core.util.type.KualiDecimal; | |
24 | import org.kuali.rice.core.util.type.KualiInteger; | |
25 | import org.kuali.rice.core.util.type.KualiPercent; | |
26 | ||
27 | import javax.servlet.http.HttpServletRequest; | |
28 | import java.io.Serializable; | |
29 | import java.lang.reflect.Array; | |
30 | import java.math.BigDecimal; | |
31 | import java.sql.Date; | |
32 | import java.sql.Timestamp; | |
33 | import java.util.ArrayList; | |
34 | import java.util.Collection; | |
35 | import java.util.Collections; | |
36 | import java.util.HashMap; | |
37 | import java.util.HashSet; | |
38 | import java.util.Iterator; | |
39 | import java.util.List; | |
40 | import java.util.Map; | |
41 | import java.util.Set; | |
42 | ||
43 | ||
44 | ||
45 | // begin Kuali Foundation modification | |
46 | /** | |
47 | * This is the base class for all other Formatters. | |
48 | */ | |
49 | /** | |
50 | * It provides default formatting and conversion behavior for most value types, including primitives, arrays, and instances of most | |
51 | * {@link Collection}types. <code>Formatter</code> and its subclasses were designed primarily to be used by web app framework | |
52 | * components, though they can also be used in other contexts. | |
53 | * <p> | |
54 | * During request processing, the {@link PojoActionForm}uses <code>Formatter</code> instances to convert inbound request values | |
55 | * to JavaBean property types. Whenever a given value cannot be converted to its target type, the conversion method | |
56 | * {@link PropertyUtils#getProperty(Object, String)}throws a {@link FormatException}to signal this condition to the | |
57 | * calling code. | |
58 | * <p> | |
59 | * During the response phase, Struts tags make calls to the {@link PojoRequestProcessor}in order to access bean property values. | |
60 | * The <code>PojoRequestProcessor</code> then uses <code>Formatter</code> instances to format the bean values for presentation | |
61 | * in the user interface. | |
62 | * <p> | |
63 | * In either case, <code>Formatter</code> instances are obtained by calling {@link #getFormatter(Class)}, which looks in an | |
64 | * internal registry to determine which <code>Formatter</code> class to instantiate, and returns a new instance. The StrutsLive | |
65 | * framework includes a number of <code>Formatter</code> classes that are registered statically; additional | |
66 | * <code>Formatter classes can be registered at compile | |
67 | * time or at run time. | |
68 | * <p> | |
69 | * Subclasses of <code>Formatter</code> typically override the callback methods | |
70 | * {@link #convertToObject(String)} and {@link #formatObject(Object)}, which | |
71 | * otherwise provide default conversion and formmating behavior needed for | |
72 | * atomic values (i.e., an ordinary bean property such as a <code>String</code> | |
73 | * or <code>Integer</code>, or else an element of a property typed as | |
74 | * array or Collection). | |
75 | * | |
76 | * @see PojoActionForm#populate(HttpServletRequest) | |
77 | * @see PojoPropertyUtilsBean#getProperty(Object, String) | |
78 | */ | |
79 | // end Kuali Foundation modification | |
80 | 1 | public class Formatter implements Serializable { |
81 | ||
82 | // begin Kuali Foundation modification | |
83 | // removed serialVersionUID and logger members | |
84 | // end Kuali Foundation modification | |
85 | ||
86 | static final String CREATE_MSG = "Couldn't create an instance of class "; | |
87 | // begin Kuali Foundation modification | |
88 | // registry changed from AppLocal instance to a Map | |
89 | 1 | private static Map registry = Collections.synchronizedMap(new HashMap()); |
90 | // end Kuali Foundation modification | |
91 | ||
92 | protected Map settings; | |
93 | ||
94 | // begin Kuali Foundation modification | |
95 | // removed keypath and rootObject variables | |
96 | // end Kuali Foundation modification | |
97 | ||
98 | protected Class propertyType; | |
99 | ||
100 | static { | |
101 | // begin Kuali Foundation modification | |
102 | 1 | registerFormatter(String.class, Formatter.class); |
103 | 1 | registerFormatter(String[].class, Formatter.class); |
104 | 1 | registerFormatter(AbstractKualiDecimal.class, BigDecimalFormatter.class); |
105 | 1 | registerFormatter(KualiDecimal.class, CurrencyFormatter.class); |
106 | 1 | registerFormatter(KualiInteger.class, KualiIntegerCurrencyFormatter.class); |
107 | 1 | registerFormatter(KualiPercent.class, PercentageFormatter.class); |
108 | 1 | registerFormatter(BigDecimal.class, BigDecimalFormatter.class); |
109 | 1 | registerFormatter(Date.class, DateFormatter.class); |
110 | 1 | registerFormatter(Integer.class, IntegerFormatter.class); |
111 | 1 | registerFormatter(int.class, IntegerFormatter.class); |
112 | 1 | registerFormatter(int[].class, IntegerFormatter.class); |
113 | 1 | registerFormatter(Boolean.class, BooleanFormatter.class); |
114 | 1 | registerFormatter(Boolean.TYPE, BooleanFormatter.class); |
115 | 1 | registerFormatter(boolean[].class, BooleanFormatter.class); |
116 | 1 | registerFormatter(Long.class, LongFormatter.class); |
117 | 1 | registerFormatter(Timestamp.class, DateViewTimestampObjectFormatter.class); |
118 | 1 | registerFormatter(boolean.class, LittleBooleanFormatter.class); |
119 | 1 | registerFormatter(Collection.class, ArrayFormatter.class); |
120 | // end Kuali Foundation modification | |
121 | 1 | } |
122 | ||
123 | public static Formatter getFormatter(Class aType) { | |
124 | 0 | return getFormatter(aType, null); |
125 | } | |
126 | ||
127 | // begin Kuali Foundation modification | |
128 | // param aType was valueType, comment changes, major code changes | |
129 | /** | |
130 | * Returns an instance of the Formatter class to be used to format the provided value type. | |
131 | * | |
132 | * @param type the class of the value to be formatted | |
133 | * @param settings parameters used by subclasses to customize behavior | |
134 | * @return an instance of Formatter or one of its subclasses | |
135 | */ | |
136 | public static Formatter getFormatter(Class aType, Map settings) { | |
137 | // original code: return createFormatter(formatterForType(valueType), valueType, settings); | |
138 | ||
139 | 1 | Class type = formatterForType(aType); |
140 | 1 | Formatter formatter = null; |
141 | try { | |
142 | 1 | formatter = (Formatter) type.newInstance(); |
143 | } | |
144 | 0 | catch (InstantiationException e) { |
145 | 0 | throw new FormatException(CREATE_MSG + type, e); |
146 | } | |
147 | 0 | catch (IllegalAccessException e) { |
148 | 0 | throw new FormatException(CREATE_MSG + type, e); |
149 | 1 | } |
150 | ||
151 | 1 | if (settings != null) |
152 | 0 | formatter.setSettings(Collections.unmodifiableMap(settings)); |
153 | 1 | formatter.propertyType = aType; |
154 | ||
155 | 1 | return formatter; |
156 | } | |
157 | ||
158 | // removed getFormatterByName, formatterClassForName, createFormatter methods | |
159 | // end Kuali Foundation modification | |
160 | ||
161 | /** | |
162 | * Binds the provided value type to a Formatter type. Note that a single Formatter class can be associated with more than one | |
163 | * type. | |
164 | * | |
165 | * @param type a value type | |
166 | * @param formatterType a Formatter type | |
167 | */ | |
168 | public static void registerFormatter(Class type, Class formatterType) { | |
169 | 18 | registry.put(type, formatterType); |
170 | 18 | } |
171 | ||
172 | /** | |
173 | * Returns <code>true</code> if the provided class is an array type, implements either the {@link List}or {@link Set} | |
174 | * interfaces, or is one of the Formatter classes currently registered. | |
175 | * | |
176 | * @see registerFormatter(Class, Class) | |
177 | */ | |
178 | public static boolean isSupportedType(Class type) { | |
179 | // begin Kuali Foundation modification | |
180 | 0 | if (type == null) |
181 | 0 | return false; |
182 | // end Kuali Foundation modification | |
183 | 0 | if (List.class.isAssignableFrom(type)) |
184 | 0 | return true; |
185 | 0 | if (Set.class.isAssignableFrom(type)) |
186 | 0 | return true; |
187 | ||
188 | 0 | return findFormatter(type) != null; |
189 | } | |
190 | ||
191 | /** | |
192 | * Return the Formatter associated with the given type, by consulting an internal registry. Additional associations can be made | |
193 | * by calling {@link registerFormatter(Class, Class)}. | |
194 | * | |
195 | * @return a new Formatter instance | |
196 | */ | |
197 | public static Class formatterForType(Class type) { | |
198 | 1 | if (type == null) |
199 | 0 | throw new IllegalArgumentException("Type can not be null"); |
200 | ||
201 | 1 | Class formatterType = findFormatter(type); |
202 | ||
203 | 1 | return formatterType == null ? Formatter.class : formatterType; |
204 | } | |
205 | ||
206 | // Kuali Foundation modification: comment removed | |
207 | public static Class findFormatter(Class type) { | |
208 | // begin Kuali Foundation modification | |
209 | 1 | if (type == null) |
210 | 0 | return null; |
211 | ||
212 | 1 | if (registry.containsKey(type)) { |
213 | 1 | return (Class) registry.get(type); |
214 | } | |
215 | ||
216 | ||
217 | 0 | Iterator typeIter = registry.keySet().iterator(); |
218 | 0 | while (typeIter.hasNext()) { |
219 | 0 | Class currType = (Class) typeIter.next(); |
220 | 0 | if (currType.isAssignableFrom(type)) { |
221 | 0 | Class currFormatter = (Class) registry.get(currType); |
222 | 0 | registerFormatter(type, currFormatter); |
223 | 0 | return currFormatter; |
224 | } | |
225 | 0 | } |
226 | ||
227 | 0 | return null; |
228 | // end Kuali Foundation modification | |
229 | } | |
230 | ||
231 | // begin Kuali Foundation modification | |
232 | public String getImplementationClass() { | |
233 | 0 | return this.getClass().getName(); |
234 | } | |
235 | // end Kuali Foundation modification | |
236 | ||
237 | public Class getPropertyType() { | |
238 | 0 | return propertyType; |
239 | } | |
240 | ||
241 | public void setPropertyType(Class propertyType) { | |
242 | 0 | this.propertyType = propertyType; |
243 | 0 | } |
244 | ||
245 | public Map getSettings() { | |
246 | 0 | return settings; |
247 | } | |
248 | ||
249 | public void setSettings(Map settings) { | |
250 | 0 | this.settings = settings; |
251 | 0 | } |
252 | ||
253 | // begin Kuali Foundation modification | |
254 | // removed getKeypath, setKeyPath, getRootObject, setRootObject, hasSettingForKey, settingForKey, typeForKey, getErrorKey | |
255 | // end Kuali Foundation modification | |
256 | ||
257 | /** | |
258 | * begin Kuali Foundation modification | |
259 | * Returns a String representation of the given value. May be overridden by subclasses to provide customized behavior for | |
260 | * different types, though generally the callback method {@link #format(Object)}provides a better customization hook. | |
261 | * <p> | |
262 | * Provides default handling for properties typed as array or Collection. Subclass implementations of this method must invoke | |
263 | * <code>super.formatForPresentation()</code> to take advantage of this built-in behavior. | |
264 | * <p> | |
265 | * Delegates to callback method {@link formatObject}for all other types. This method in turn invokes the callback method | |
266 | * <code>format</code>, which serves as an extension point for subclasses; the default implementation simply returns its | |
267 | * argument. Overriding <code>format</code> allows subclasses to take advantage of all of the array, primitive type, and | |
268 | * Collection handling functionality provided by the base class. | |
269 | * | |
270 | * @param value the object to be formatted | |
271 | * @return a formatted string representation of the given object | |
272 | * @see #formatObject(Object) | |
273 | * end Kuali Foundation modification | |
274 | */ | |
275 | public Object formatForPresentation(Object value) { | |
276 | 0 | if (isNullValue(value)) |
277 | 0 | return formatNull(); |
278 | ||
279 | // begin Kuali Foundation modification | |
280 | // removed code | |
281 | /* | |
282 | // TODO: add registry for non-navigable classes so there's a way to | |
283 | // disable formatting selectively for given types contained in arrays | |
284 | // or Collections. | |
285 | if (Collection.class.isAssignableFrom(value.getClass())) | |
286 | return formatCollection((Collection) value); | |
287 | | |
288 | if (propertyType != null && propertyType.isArray()) | |
289 | return formatArray(value); | |
290 | */ | |
291 | // end Kuali Foundation modification | |
292 | ||
293 | 0 | return formatObject(value); |
294 | } | |
295 | ||
296 | /** | |
297 | * May be overridden by subclasses to provide special handling for <code>null</code> values when formatting a bean property | |
298 | * value for presentation. The default implementation simply returns <code>null</code> | |
299 | */ | |
300 | protected Object formatNull() { | |
301 | 0 | return null; |
302 | } | |
303 | ||
304 | /** | |
305 | * May be overridden by subclasses to provide custom formatting behavior. Provides default formatting implementation for | |
306 | * primitive types. (Note that primitive types are will always be wrapped in an array in order to be passed as an argument of | |
307 | * type <code>Object</code>). | |
308 | */ | |
309 | public Object formatObject(Object value) { | |
310 | 0 | if (value == null) |
311 | 0 | return formatNull(); |
312 | ||
313 | // Collections and arrays have already been handled at this point, so | |
314 | // if value is an array, assume it's a wrapper for a primitive type. | |
315 | 0 | Class<?> type = value.getClass(); |
316 | 0 | if (type.isArray()) |
317 | // begin Kuali Foundation modification | |
318 | 0 | return ArrayUtils.toString(value, type.getComponentType()); |
319 | // end begin Kuali Foundation modification | |
320 | ||
321 | 0 | if (!(isSupportedType(value.getClass()))) |
322 | // begin Kuali Foundation modification | |
323 | 0 | formatBean(value); |
324 | // end Kuali Foundation modification | |
325 | ||
326 | 0 | return format(value); |
327 | } | |
328 | ||
329 | /** | |
330 | * If an element of the Collection isn't a supported type, assume it's a JavaBean, and format each of its properties. Returns a | |
331 | * Map containing the formatted properties keyed by property name. | |
332 | */ | |
333 | protected Object formatBean(Object bean) { | |
334 | 0 | Map properties = null; |
335 | try { | |
336 | // begin Kuali Foundation modification | |
337 | 0 | properties = PropertyUtils.describe(bean); |
338 | // end Kuali Foundation modification | |
339 | } | |
340 | 0 | catch (Exception e) { |
341 | 0 | throw new FormatException("Unable to format values for bean " + bean, e); |
342 | 0 | } |
343 | ||
344 | 0 | Map formattedVals = new HashMap(); |
345 | // begin Kuali Foundation modification | |
346 | 0 | Iterator propIter = properties.entrySet().iterator(); |
347 | ||
348 | 0 | while (propIter.hasNext()) { |
349 | 0 | Map.Entry entry = (Map.Entry) propIter.next(); |
350 | 0 | Object value = entry.getValue(); |
351 | 0 | if (value != null && isSupportedType(value.getClass())) { |
352 | 0 | Formatter formatter = getFormatter(value.getClass()); |
353 | 0 | formattedVals.put(entry.getKey(), formatter.formatForPresentation(value)); |
354 | } | |
355 | 0 | } |
356 | // end Kuali Foundation modification | |
357 | 0 | return formattedVals; |
358 | } | |
359 | ||
360 | public Object format(Object value) { | |
361 | 0 | return value; |
362 | } | |
363 | ||
364 | public Object formatArray(Object value) { | |
365 | // begin Kuali Foundation modification | |
366 | 0 | Class elementType = value.getClass().getComponentType(); |
367 | 0 | if (!isSupportedType(elementType)) |
368 | 0 | return value; |
369 | ||
370 | 0 | int length = Array.getLength(value); |
371 | 0 | Object[] formattedVals = new String[length]; |
372 | ||
373 | 0 | for (int i = 0; i < length; i++) { |
374 | 0 | Object element = Array.get(value, i); |
375 | 0 | Object objValue = ArrayUtils.toObject(element); |
376 | 0 | Formatter elementFormatter = getFormatter(elementType); |
377 | 0 | formattedVals[i] = elementFormatter.formatForPresentation(objValue); |
378 | } | |
379 | ||
380 | 0 | return formattedVals; |
381 | // end Kuali Foundation modification | |
382 | } | |
383 | ||
384 | public Object formatCollection(Collection value) { | |
385 | 0 | List stringVals = new ArrayList(); |
386 | 0 | Iterator iter = value.iterator(); |
387 | 0 | while (iter.hasNext()) { |
388 | 0 | Object obj = iter.next(); |
389 | 0 | Formatter formatter = getFormatter(obj.getClass()); |
390 | // begin Kuali Foundation modification | |
391 | 0 | stringVals.add(formatter.formatForPresentation(obj)); |
392 | // end Kuali Foundation modification | |
393 | 0 | } |
394 | 0 | return stringVals.toArray(); |
395 | } | |
396 | ||
397 | /** | |
398 | * Returns an object representation of the provided string after first removing any extraneous formatting characters. If the | |
399 | * argument is a native array wrapping the actual value, the value is removed (unwrapped) from the array prior to invoking the | |
400 | * callback method {@link #convertToObject(String)}, which performs the actual conversion. | |
401 | * <p> | |
402 | * If the provided object is <code>null</code>, a blank <code>String</code>, or a <code>String[]</code> of length <b>0 | |
403 | * </b> or that has <code>null</code> or a blank <code>String</code> in the first position, returns <code>null</code>. | |
404 | * Otherwise, If the destination property is a <code>Collection</code>, returns an instance of that type containing the | |
405 | * string values of the array elements. | |
406 | * <p> | |
407 | * If the provided object is an array, uses a Formatter corresponding to the array's component type to convert each of its | |
408 | * elements, and returns a new array containing the converted values. | |
409 | * | |
410 | * May be overidden by subclasses to customize conversion, though ordinarily {@link #convertToObject(String)}is a better choice | |
411 | * since it takes advantage of <code>convertFromPresentationFormat</code>'s built-in behavior. | |
412 | * | |
413 | * @param value the string value to be converted | |
414 | * @return the object value corresponding to the provided string value | |
415 | * @see convertToObject(String) | |
416 | */ | |
417 | public Object convertFromPresentationFormat(Object value) { | |
418 | 0 | if (isEmptyValue(value)) |
419 | 0 | return getNullObjectValue(); |
420 | ||
421 | 0 | Class type = value.getClass(); |
422 | 0 | boolean isArray = propertyType != null && propertyType.isArray(); |
423 | 0 | boolean isCollection = propertyType != null && Collection.class.isAssignableFrom(propertyType); |
424 | ||
425 | 0 | if (!(isArray || isCollection)) { |
426 | 0 | value = unwrapString(value); |
427 | 0 | return convertToObject((String) value); |
428 | } | |
429 | ||
430 | 0 | String[] strings = type.isArray() ? (String[]) value : new String[] { (String) value }; |
431 | ||
432 | 0 | return isArray ? convertToArray(strings) : convertToCollection(strings); |
433 | } | |
434 | ||
435 | /** | |
436 | * May be overridden by subclasses to provide special handling for <code>null</code> values when converting from presentation | |
437 | * format to a bean property type. The default implementation simply returns <code>null</code> | |
438 | */ | |
439 | protected Object getNullObjectValue() { | |
440 | 0 | return null; |
441 | } | |
442 | ||
443 | /** | |
444 | * May be orverridden by subclasses to customize its behavior. The default implementation simply trims and returns the provided | |
445 | * string. | |
446 | */ | |
447 | protected Object convertToObject(String string) { | |
448 | 0 | return string == null ? null : string.replace( "\r\n", "\n" ).trim(); |
449 | } | |
450 | ||
451 | /** | |
452 | * Converts an array of strings to a Collection type corresponding to the value of <code>propertyType</code>. Since we don't | |
453 | * have type information for the elements of the collection, no attempt is made to convert the elements from <code>String</code> | |
454 | * to other types. However, subclasses can override this method if they need to provide the ability to convert the elements to a | |
455 | * given type. | |
456 | */ | |
457 | protected Collection convertToCollection(String[] strings) { | |
458 | 0 | Collection collection = null; |
459 | 0 | Class type = propertyType; |
460 | ||
461 | 0 | if (propertyType.isAssignableFrom(List.class)) |
462 | 0 | type = ArrayList.class; |
463 | 0 | else if (propertyType.isAssignableFrom(Set.class)) |
464 | 0 | type = HashSet.class; |
465 | ||
466 | try { | |
467 | 0 | collection = (Collection) type.newInstance(); |
468 | } | |
469 | 0 | catch (Exception e) { |
470 | 0 | throw new FormatException(CREATE_MSG + propertyType, e); |
471 | 0 | } |
472 | ||
473 | 0 | for (int i = 0; i < strings.length; i++) |
474 | 0 | collection.add(strings[i]); |
475 | ||
476 | 0 | return collection; |
477 | } | |
478 | ||
479 | /** | |
480 | * Converts an array of strings to an array of objects by calling {@link #convertToObject(String)}on each element of the | |
481 | * provided array in turn, using instances of a Formatter class that corresponds to this Formatter's property type. | |
482 | * | |
483 | * @see #propertyType | |
484 | */ | |
485 | protected Object convertToArray(String[] strings) { | |
486 | 0 | Class type = propertyType.getComponentType(); |
487 | // begin Kuali Foundation modification | |
488 | 0 | Formatter formatter = getFormatter(type); |
489 | // end Kuali Foundation modification | |
490 | 0 | Object array = null; |
491 | try { | |
492 | 0 | array = Array.newInstance(type, strings.length); |
493 | } | |
494 | 0 | catch (Exception e) { |
495 | 0 | throw new FormatException(CREATE_MSG + type, e); |
496 | 0 | } |
497 | ||
498 | 0 | for (int i = 0; i < strings.length; i++) { |
499 | 0 | Object value = formatter.convertToObject(strings[i]); |
500 | // begin Kuali Foundation modification | |
501 | 0 | ArrayUtils.setArrayValue(array, type, value, i); |
502 | // end Kuali Foundation modification | |
503 | } | |
504 | ||
505 | 0 | return array; |
506 | } | |
507 | ||
508 | public static String unwrapString(Object target) { | |
509 | ||
510 | 0 | if (target.getClass().isArray()) { |
511 | 0 | String wrapper[] = (String[]) target; |
512 | 0 | return wrapper.length > 0 ? wrapper[0] : null; |
513 | } | |
514 | // begin Kuali Foundation modification | |
515 | // if target object is null, return a null String | |
516 | 0 | else if (target == null) { |
517 | 0 | return new String(); |
518 | } | |
519 | ||
520 | // otherwise, return the string value of the object, with the hope | |
521 | // that the toString() has been meaningfully overriden | |
522 | else { | |
523 | 0 | return target.toString(); |
524 | } | |
525 | // end Kuali Foundation modification | |
526 | } | |
527 | ||
528 | public static boolean isNullValue(Object obj) { | |
529 | 0 | if (obj == null) |
530 | 0 | return true; |
531 | ||
532 | // begin Kuali Foundation modification | |
533 | 0 | if ((obj instanceof String) && StringUtils.isEmpty((String) obj)) |
534 | 0 | return true; |
535 | // end Kuali Foundation modification | |
536 | ||
537 | 0 | return false; |
538 | } | |
539 | ||
540 | public static boolean isEmptyValue(Object obj) { | |
541 | 0 | if (obj == null) |
542 | 0 | return true; |
543 | // begin Kuali Foundation modification | |
544 | 0 | if ((obj instanceof String) && StringUtils.isEmpty((String) obj)) |
545 | 0 | return true; |
546 | // end Kuali Foundation modification | |
547 | 0 | Class type = obj.getClass(); |
548 | 0 | if (type.isArray()) { |
549 | 0 | Class compType = type.getComponentType(); |
550 | 0 | if (compType.isPrimitive()) |
551 | 0 | return false; |
552 | 0 | if (((Object[]) obj).length == 0) |
553 | 0 | return true; |
554 | 0 | if (((Object[]) obj)[0] == null) |
555 | 0 | return true; |
556 | 0 | if (String.class.isAssignableFrom(compType)) { |
557 | // begin Kuali Foundation modification | |
558 | 0 | return StringUtils.isEmpty(((String[]) obj)[0]); |
559 | // end Kuali Foundation modification | |
560 | } | |
561 | } | |
562 | 0 | return false; |
563 | } | |
564 | ||
565 | protected String trimString(Object target) { | |
566 | 0 | String stringValue = null; |
567 | try { | |
568 | 0 | stringValue = (String) target; |
569 | } | |
570 | 0 | catch (ClassCastException e) { |
571 | 0 | throw new FormatException("Can't cast " + target + " to String", e); |
572 | 0 | } |
573 | 0 | return stringValue == null ? null : stringValue.trim(); |
574 | } | |
575 | ||
576 | /** | |
577 | * begin Kuali Foundation modification | |
578 | * This class sets the value of an element of an array of primitives at the supplied index. | |
579 | * end Kuali Foundation modification | |
580 | * @author Kuali Rice Team (rice.collab@kuali.org) | |
581 | */ | |
582 | 1 | protected static final class ArrayUtils { |
583 | ||
584 | 0 | private ArrayUtils() { |
585 | 0 | throw new UnsupportedOperationException("do not call"); |
586 | } | |
587 | ||
588 | /** | |
589 | * Sets the value of an element of an array of primitives at the supplied index. | |
590 | * | |
591 | * @param array An array. | |
592 | * @param type The component type of the array. | |
593 | * @param index An array index. | |
594 | */ | |
595 | public static void setArrayValue(Object array, Class type, Object value, int index) { | |
596 | 0 | if (!type.isPrimitive()) |
597 | 0 | Array.set(array, index, value); |
598 | 0 | else if (type.isAssignableFrom(Boolean.TYPE)) |
599 | 0 | Array.setBoolean(array, index, (Boolean) value); |
600 | 0 | else if (type.isAssignableFrom(Character.TYPE)) |
601 | 0 | Array.setChar(array, index, (Character) value); |
602 | 0 | else if (type.isAssignableFrom(Byte.TYPE)) |
603 | 0 | Array.setByte(array, index, (Byte) value); |
604 | 0 | else if (type.isAssignableFrom(Integer.TYPE)) |
605 | 0 | Array.setInt(array, index, (Integer) value); |
606 | 0 | else if (type.isAssignableFrom(Short.TYPE)) |
607 | 0 | Array.setShort(array, index, (Short) value); |
608 | 0 | else if (type.isAssignableFrom(Long.TYPE)) |
609 | 0 | Array.setLong(array, index, (Long) value); |
610 | 0 | else if (type.isAssignableFrom(Float.TYPE)) |
611 | 0 | Array.setFloat(array, index, (Float) value); |
612 | 0 | else if (type.isAssignableFrom(Double.TYPE)) |
613 | 0 | Array.setDouble(array, index, (Double) value); |
614 | 0 | } |
615 | ||
616 | public static Object toObject(Object value) { | |
617 | 0 | if (!value.getClass().isArray()) |
618 | 0 | return value; |
619 | ||
620 | 0 | Class type = value.getClass().getComponentType(); |
621 | 0 | if (Array.getLength(value) == 0) |
622 | 0 | return null; |
623 | 0 | if (!type.isPrimitive()) |
624 | 0 | return Array.get(value, 0); |
625 | 0 | if (boolean.class.isAssignableFrom(type)) |
626 | 0 | return Array.getBoolean(value, 0); |
627 | 0 | if (char.class.isAssignableFrom(type)) |
628 | 0 | return new Character(Array.getChar(value, 0)); |
629 | 0 | if (byte.class.isAssignableFrom(type)) |
630 | 0 | return new Byte(Array.getByte(value, 0)); |
631 | 0 | if (int.class.isAssignableFrom(type)) |
632 | 0 | return new Integer(Array.getInt(value, 0)); |
633 | 0 | if (long.class.isAssignableFrom(type)) |
634 | 0 | return new Long(Array.getLong(value, 0)); |
635 | 0 | if (short.class.isAssignableFrom(type)) |
636 | 0 | return new Short(Array.getShort(value, 0)); |
637 | 0 | if (double.class.isAssignableFrom(type)) |
638 | 0 | return new Double(Array.getDouble(value, 0)); |
639 | 0 | if (float.class.isAssignableFrom(type)) |
640 | 0 | return new Float(Array.getFloat(value, 0)); |
641 | ||
642 | 0 | return null; |
643 | } | |
644 | ||
645 | public static Object toString(Object array, Class type) { | |
646 | 0 | if (boolean.class.isAssignableFrom(type)) |
647 | 0 | return Boolean.toString(((boolean[]) array)[0]); |
648 | 0 | if (char.class.isAssignableFrom(type)) |
649 | 0 | return Character.toString(((char[]) array)[0]); |
650 | 0 | if (byte.class.isAssignableFrom(type)) |
651 | 0 | return Byte.toString(((byte[]) array)[0]); |
652 | 0 | if (int.class.isAssignableFrom(type)) |
653 | 0 | return Integer.toString(((int[]) array)[0]); |
654 | 0 | if (long.class.isAssignableFrom(type)) |
655 | 0 | return Long.toString(((long[]) array)[0]); |
656 | 0 | if (short.class.isAssignableFrom(type)) |
657 | 0 | return Short.toString(((short[]) array)[0]); |
658 | 0 | if (double.class.isAssignableFrom(type)) |
659 | 0 | return Double.toString(((double[]) array)[0]); |
660 | 0 | if (float.class.isAssignableFrom(type)) |
661 | 0 | return Float.toString(((float[]) array)[0]); |
662 | ||
663 | 0 | return ((String[]) array)[0]; |
664 | } | |
665 | } | |
666 | } |