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