Coverage Report - org.kuali.rice.core.web.format.Formatter
 
Classes in this File Line Coverage Branch Coverage Complexity
Formatter
20%
37/184
5%
5/100
5.194
Formatter$ArrayUtils
0%
0/62
0%
0/56
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  
 }