package org.apache.velocity.tools;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import java.io.File;
import java.lang.reflect.Array;
import java.net.URL;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.FieldPosition;
import java.text.NumberFormat;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.LoggerFactory;

/**
 * Utility methods for parsing or otherwise converting between types.
 * Current supported types are Number, Date, Calendar, 
 * String, Boolean, Locale and URL
 *
 * @author Nathan Bubna
 */
public class ConversionUtils
{
    public static final ConversionUtils INSTANCE = new ConversionUtils();

    /*
     * Number formatting and parsing utilities
     */

    private static final int STYLE_NUMBER       = 0;
    private static final int STYLE_CURRENCY     = 1;
    private static final int STYLE_PERCENT      = 2;
    //NOTE: '3' belongs to a non-public "scientific" style
    private static final int STYLE_INTEGER      = 4;

    // cache custom formats
    private static ConcurrentMap<String,NumberFormat> customFormatsCache = new ConcurrentHashMap<String,NumberFormat>();

    private ConversionUtils() {}

    public ConversionUtils getInstance()
    {
        return INSTANCE;
    }


    /**
     * Returns a {@link NumberFormat} instance for the specified
     * format and {@link Locale}.  If the format specified is a standard
     * style pattern, then a number instance
     * will be returned with the number style set to the
     * specified style.  If it is a custom format, then a customized
     * {@link NumberFormat} will be returned.
     *
     * @param format the custom or standard formatting pattern to be used
     * @param locale the {@link Locale} to be used
     * @return an instance of {@link NumberFormat}
     * @see NumberFormat
     */
    public static NumberFormat getNumberFormat(String format, Locale locale)
    {
        if (format == null || locale == null)
        {
            return null;
        }

        NumberFormat nf = null;
        int style = getNumberStyleAsInt(format);
        if (style < 0)
        {
            // we have a custom format
            String cacheKey = format + "%" + locale.toString();
            nf = customFormatsCache.get(cacheKey);
            if( nf == null )
            {
                nf = new DecimalFormat(format, new DecimalFormatSymbols(locale));
                customFormatsCache.put(cacheKey,nf);
            }
        }
        else
        {
            // we have a standard format
            nf = getNumberFormat(style, locale);
        }
        return nf;
    }

    /**
     * Returns a {@link NumberFormat} instance for the specified
     * number style and {@link Locale}.
     *
     * @param numberStyle the number style (number will be ignored if this is
     *        less than zero or the number style is not recognized)
     * @param locale the {@link Locale} to be used
     * @return an instance of {@link NumberFormat} or <code>null</code>
     *         if an instance cannot be constructed with the given
     *         parameters
     */
    public static NumberFormat getNumberFormat(int numberStyle, Locale locale)
    {
        try
        {
            NumberFormat nf;
            switch (numberStyle)
            {
                case STYLE_NUMBER:
                    nf = NumberFormat.getNumberInstance(locale);
                    break;
                case STYLE_CURRENCY:
                    nf = NumberFormat.getCurrencyInstance(locale);
                    break;
                case STYLE_PERCENT:
                    nf = NumberFormat.getPercentInstance(locale);
                    break;
                case STYLE_INTEGER:
                    nf = NumberFormat.getIntegerInstance(locale);
                    break;
                default:
                    // invalid style was specified, return null
                    nf = null;
            }
            return nf;
        }
        catch (Exception suppressed)
        {
            // let it go...
            return null;
        }
    }

    /**
     * Checks a string to see if it matches one of the standard
     * NumberFormat style patterns:
     *      number, currency, percent, integer, or default.
     * if it does it will return the integer constant for that pattern.
     * if not, it will return -1.
     *
     * @see NumberFormat
     * @param style the string to be checked
     * @return the int identifying the style pattern
     */
    public static int getNumberStyleAsInt(String style)
    {
        // avoid needlessly running through all the string comparisons
        if (style == null || style.length() < 6 || style.length() > 8) {
            return -1;
        }
        if (style.equalsIgnoreCase("default"))
        {
            //NOTE: java.text.NumberFormat returns "number" instances
            //      as the default (at least in Java 1.3 and 1.4).
            return STYLE_NUMBER;
        }
        if (style.equalsIgnoreCase("number"))
        {
            return STYLE_NUMBER;
        }
        if (style.equalsIgnoreCase("currency"))
        {
            return STYLE_CURRENCY;
        }
        if (style.equalsIgnoreCase("percent"))
        {
            return STYLE_PERCENT;
        }
        if (style.equalsIgnoreCase("integer"))
        {
            return STYLE_INTEGER;
        }
        // ok, it's not any of the standard patterns
        return -1;
    }


    // ----------------- number conversion methods ---------------

    /**
     * Attempts to convert an unidentified {@link Object} into a {@link Number},
     * just short of turning it into a string and parsing it.  In other words,
     * this will convert to {@link Number} from a {@link Number}, {@link Calendar},
     * or {@link Date}.  If it can't do that, it will get the string value and have 
     * {@link #toNumber(String,String,Locale)} try to parse it using the
     * default Locale and format.
     * @param obj - the object to convert
     * @return the converted Number or null if the conversion failed
     */
    public static Number toNumber(Object obj)
    {
        return toNumber(obj, true);
    }

    /**
     * Just like {@link #toNumber(Object)} except that you can tell
     * this to attempt parsing the object as a String by passing {@code true}
     * as the second parameter.  If you do so, then it will have
     * {@link #toNumber(String,String,Locale)} try to parse it using the
     * default Locale and format.
     * @param obj the target object
     * @param handleStrings whether to try to convert from a string
     * @return the converted Number or null if the conversion failed
     */
    public static Number toNumber(Object obj, boolean handleStrings)
    {
        if (obj == null)
        {
            return null;
        }
        if (obj instanceof Number)
        {
            return (Number)obj;
        }
        if (obj instanceof Date)
        {
            return Long.valueOf(((Date)obj).getTime());
        }
        if (obj instanceof Calendar)
        {
            Date date = ((Calendar)obj).getTime();
            return Long.valueOf(date.getTime());
        }
        if (handleStrings)
        {
            // try parsing with default format and locale
            return toNumber(obj.toString(), "default", Locale.getDefault());
        }
        return null;
    }

    /**
     * Converts a string to an instance of {@link Number} using the
     * specified format and {@link Locale} to parse it.
     *
     * @param value - the string to convert
     * @param format - the format the number is in
     * @param locale - the {@link Locale}
     * @return the string as a {@link Number} or <code>null</code> if no
     *         conversion is possible
     * @see NumberFormat#parse
     */
    public static Number toNumber(String value, String format, Locale locale)
    {
        if (value == null || format == null || locale == null)
        {
            return null;
        }
        try
        {
            NumberFormat parser = getNumberFormat(format, locale);
            return parser.parse(value);
        }
        catch (Exception e)
        {
            return null;
        }
    }

    /**
     * Converts an object to an instance of {@link Number} using the
     * specified format and {@link Locale} to parse it, if necessary.
     *
     * @param value - the object to convert
     * @param format - the format the number is in
     * @param locale - the {@link Locale}
     * @return the object as a {@link Number} or <code>null</code> if no
     *         conversion is possible
     * @see NumberFormat#parse
     */
    public static Number toNumber(Object value, String format, Locale locale)
    {
        // first try the easy stuff
        Number number = toNumber(value, false);
        if (number != null)
        {
            return number;
        }

        // turn it into a string and try parsing it
        return toNumber(String.valueOf(value), format, locale);
    }

    /*
     * Date/time formatting & parsing utilities
     */

    /* Java DateFormat standard constants extensions */
    private static final int STYLE_ISO = 5;  /* ISO 8601 format */
    private static final int STYLE_ISO_TZ = 6; /* ISO 8601 format with timezone offset */
    private static final int STYLE_INTL = 7;  /* ISO 8601 human-readable format */
    private static final int STYLE_INTL_TZ = 8; /* ISO 8601 human-readable format with timezone ID */

    /* iso/intl date/time formats (locale-independant) */
    private static DateFormat isoDateFormat = new SimpleDateFormat("yyyy-MM-dd");  /* ISO 8601 date */
    private static DateFormat isoTimeFormat = new SimpleDateFormat("HH:mm:ss"); /* ISO 8601 time */
    private static DateFormat isoTimestampFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); /* ISO 8601 timestamp */
    private static DateFormat intlTimestampFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");   /* human-readable ISO 8601 timestamp */
    private static DateFormat isoTimeTzFormat = new SimpleDateFormat("HH:mm:ssXXX"); /* ISO 8601 time with timezone offset */
    private static DateFormat isoTimestampTzFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"); /* ISO 8601 timestamp with timezone offset */
    private static DateFormat intlTimeTzFormat_base = new SimpleDateFormat("HH:mm:ss");   /* human-readable ISO 8601 time with timezone ID */
    private static DateFormat intlTimestampTzFormat_base = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");   /* human-readable ISO 8601 timestamp with timezone ID */

    /* a DateFormat that appends a space and the time zone ID to the wrapped DateFormat - needed because
    * there is no letter format for time zone id in SimpleDateFormat. */
    private static class TimeZoneIDSuffixFormat extends DateFormat
    {
        TimeZoneIDSuffixFormat(DateFormat wrappedFormat)
        {
            this.wrappedFormat = wrappedFormat;
            this.calendar = wrappedFormat.getCalendar();
            this.numberFormat = wrappedFormat.getNumberFormat();
        }

        @Override
        public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition)
        {
            StringBuffer sb = wrappedFormat.format(date, toAppendTo, fieldPosition);
            sb.append(' ');
            sb.append(getTimeZone().getID());
            return sb;
        }

        /* This format is only here for formatting purposes... */
        @Override
        public Date parse(String source, ParsePosition pos)
        {
            throw new UnsupportedOperationException("intl_tz date/time formats cannot be used to parse dates");
        }

        @Override
        public void setCalendar(Calendar newCalendar)
        {
            super.setCalendar(newCalendar);
            wrappedFormat.setCalendar(newCalendar);
        }

        @Override
        public void setNumberFormat(NumberFormat newNumberFormat)
        {
            super.setNumberFormat(newNumberFormat);
            wrappedFormat.setNumberFormat(newNumberFormat);
        }

        /* no need to override setCalendar, since the calendar is shared between us and the wrapped format */

        private DateFormat wrappedFormat;
    }

    /**
     * Returns a {@link DateFormat} instance for the specified
     * format, {@link Locale}, and {@link TimeZone}.  If the format
     * specified is a standard style pattern, then a date-time instance
     * will be returned with both the date and time styles set to the
     * specified style.  If it is a custom format, then a customized
     * {@link SimpleDateFormat} will be returned.
     *
     * @param format the custom or standard formatting pattern to be used
     * @param locale the {@link Locale} to be used
     * @param timezone the {@link TimeZone} to be used
     * @return an instance of {@link DateFormat}
     * @see SimpleDateFormat
     * @see DateFormat
     */
    public static DateFormat getDateFormat(String format, Locale locale,
                                           TimeZone timezone)
    {
        if (format == null)
        {
            return null;
        }

        DateFormat df = null;
        // do they want a date instance
        if (format.endsWith("_date"))
        {
            String fmt = format.substring(0, format.length() - 5);
            int style = getDateStyleAsInt(fmt);
            df = getDateFormat(style, -1, locale, timezone);
        }
        // do they want a time instance?
        else if (format.endsWith("_time"))
        {
            String fmt = format.substring(0, format.length() - 5);
            int style = getDateStyleAsInt(fmt);
            df = getDateFormat(-1, style, locale, timezone);
        }
        // ok, they either want a custom or date-time instance
        else
        {
            int style = getDateStyleAsInt(format);
            if (style < 0)
            {
                // we have a custom format
                df = new SimpleDateFormat(format, locale);
                df.setTimeZone(timezone);
            }
            else
            {
                // they want a date-time instance
                df = getDateFormat(style, style, locale, timezone);
            }
        }
        return df;
    }

    /**
     * Returns a {@link DateFormat} instance for the specified
     * date style, time style, {@link Locale}, and {@link TimeZone}.
     *
     * @param dateStyle the date style
     * @param timeStyle the time style
     * @param locale the {@link Locale} to be used
     * @param timezone the {@link TimeZone} to be used
     * @return an instance of {@link DateFormat}
     * @see #getDateFormat(int timeStyle, int dateStyle, Locale locale, TimeZone timezone)
     */
    public static DateFormat getDateFormat(String dateStyle, String timeStyle,
                                           Locale locale, TimeZone timezone)
    {
        int ds = getDateStyleAsInt(dateStyle);
        int ts = getDateStyleAsInt(timeStyle);
        return getDateFormat(ds, ts, locale, timezone);
    }

    /**
     * Returns a {@link DateFormat} instance for the specified
     * time style, date style, {@link Locale}, and {@link TimeZone}.
     *
     * @param dateStyle the date style (date will be ignored if this is
     *        less than zero and the date style is not)
     * @param timeStyle the time style (time will be ignored if this is
     *        less than zero and the date style is not)
     * @param locale the {@link Locale} to be used
     * @param timezone the {@link TimeZone} to be used
     * @return an instance of {@link DateFormat} or <code>null</code>
     *         if an instance cannot be constructed with the given
     *         parameters
     */
    public static DateFormat getDateFormat(int dateStyle, int timeStyle,
                                           Locale locale, TimeZone timezone)
    {
        try
        {
            DateFormat df;
            if (dateStyle < 0 && timeStyle < 0)
            {
                // no style was specified, use default instance
                df = DateFormat.getDateInstance();
            }
            else if (timeStyle < 0)
            {
                // only a date style was specified
                switch (dateStyle)
                {
                    case STYLE_ISO:
                    case STYLE_ISO_TZ: /* ignore TZ */
                    case STYLE_INTL:
                    case STYLE_INTL_TZ:  /* ignore TZ */
                        df = (DateFormat)isoDateFormat.clone();
                        break;
                    default:
                        df = DateFormat.getDateInstance(dateStyle, locale);
                        break;
                }
            }
            else if (dateStyle < 0)
            {
                // only a time style was specified
                switch (timeStyle)
                {
                    case STYLE_ISO:
                    case STYLE_INTL:
                        df = (DateFormat)isoTimeFormat.clone();
                        break;
                    case STYLE_ISO_TZ:
                        df = (DateFormat)isoTimeTzFormat.clone();
                        break;
                    case STYLE_INTL_TZ:
                        df = new TimeZoneIDSuffixFormat((DateFormat)intlTimeTzFormat_base.clone());
                        break;
                    default:
                        df = DateFormat.getTimeInstance(timeStyle, locale);
                        break;
                }
            }
            else
            {
                switch (dateStyle)
                {
                    case STYLE_ISO:
                        df = isoTimestampFormat;
                        break;
                    case STYLE_ISO_TZ:
                        df = (DateFormat)isoTimestampTzFormat.clone();
                        break;
                    case STYLE_INTL:
                        df = (DateFormat)intlTimestampFormat.clone();
                        break;
                    case STYLE_INTL_TZ:
                        df = new TimeZoneIDSuffixFormat((DateFormat)intlTimestampTzFormat_base.clone());
                        break;
                    default:
                        df = DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale);
                        break;
                }
            }
            df.setTimeZone(timezone);
            return df;
        }
        catch (Exception suppressed)
        {
            LoggerFactory.getLogger(ConversionUtils.class).error("could not get date/time format", suppressed);
            // let it go...
            return null;
        }
    }

    static Map<String, Integer> stylesMap;
    static
    {
        stylesMap = new HashMap<String, Integer>();
        stylesMap.put("FULL", DateFormat.FULL);
        stylesMap.put("LONG", DateFormat.LONG);
        stylesMap.put("MEDIUM", DateFormat.MEDIUM);
        stylesMap.put("SHORT", DateFormat.SHORT);
        stylesMap.put("DEFAULT", DateFormat.DEFAULT);
        stylesMap.put("ISO", STYLE_ISO);
        stylesMap.put("ISO_TZ", STYLE_ISO_TZ);
        stylesMap.put("INTL", STYLE_INTL);
        stylesMap.put("INTL_TZ", STYLE_INTL_TZ);
    }

    /**
     * Checks a string to see if it matches one of the standard DateFormat
     * style patterns: full, long, medium, short, or default.  If it does,
     * it will return the integer constant for that pattern.  If not, it
     * will return -1.
     *
     * @see DateFormat
     * @param style the string to be checked
     * @return the int identifying the style pattern
     */
    public static int getDateStyleAsInt(String style)
    {
        Integer intStyle = stylesMap.get(style.toUpperCase());
        return intStyle == null ? -1 : intStyle.intValue();
    }


    // ----------------- date conversion methods ---------------

    /**
     * Attempts to convert an unidentified {@link Object} into a {@link Date},
     * just short of turning it into a string and parsing it.  In other words,
     * this will convert to {@link Date} from a {@link Date}, {@link Calendar},
     * or {@link Number}.  If it can't do that, it will return {@code null}.
     *
     * @param obj - the object to convert
     * @return the converted Date, or null if the conversion failed
     */
    public static Date toDate(Object obj)
    {
        if (obj == null)
        {
            return null;
        }
        if (obj instanceof Date)
        {
            return (Date)obj;
        }
        if (obj instanceof Calendar)
        {
            return ((Calendar)obj).getTime();
        }
        if (obj instanceof Number)
        {
            Date d = new Date();
            d.setTime(((Number)obj).longValue());
            return d;
        }
        return null;
    }

    /**
     * Converts an object to an instance of {@link Date} using the
     * specified format, {@link Locale}, and {@link TimeZone} if the
     * object is not already an instance of Date, Calendar, or Long.
     *
     * @param obj - the date to convert
     * @param format - the format the date is in
     * @param locale - the {@link Locale}
     * @param timezone - the {@link TimeZone}
     * @return the object as a {@link Date} or <code>null</code> if no
     *         conversion is possible
     * @see #getDateFormat
     * @see SimpleDateFormat#parse
     */
    public static Date toDate(Object obj, String format,
                              Locale locale, TimeZone timezone)
    {
        // first try the easy stuff
        Date date = toDate(obj);
        if (date != null)
        {
            return date;
        }

        // turn it into a string and try parsing it
        return toDate(String.valueOf(obj), format, locale, timezone);
    }

    /**
     * Converts an object to an instance of {@link Date} using the
     * specified format, {@link Locale}, and {@link TimeZone} if the
     * object is not already an instance of Date, Calendar, or Long.
     *
     * @param str - the string to parse
     * @param format - the format the date is in
     * @param locale - the {@link Locale}
     * @param timezone - the {@link TimeZone}
     * @return the string as a {@link Date} or <code>null</code> if the
     *         parsing fails
     * @see #getDateFormat
     * @see SimpleDateFormat#parse
     */
    public static Date toDate(String str, String format,
                              Locale locale, TimeZone timezone)
    {
        try
        {
            //try parsing w/a customized SimpleDateFormat
            DateFormat parser = getDateFormat(format, locale, timezone);
            return parser.parse(str);
        }
        catch (Exception e)
        {
            return null;
        }
    }

    public static Calendar toCalendar(Date date, Locale locale)
    {
        if (date == null)
        {
            return null;
        }

        Calendar cal;
        if (locale == null)
        {
            cal = Calendar.getInstance();
        }
        else
        {
            cal = Calendar.getInstance(locale);
        }
        cal.setTime(date);
        // HACK: Force all fields to update. see link for explanation of this.
        //http://java.sun.com/j2se/1.4/docs/api/java/util/Calendar.html
        cal.getTime();
        return cal;
    }


    // ----------------- misc conversion methods ---------------

    /**
     * Converts objects to String in a more Tools-ish way than
     * String.valueOf(Object), especially with nulls, Arrays and Collections.
     * Null returns null, Arrays and Collections return their first value,
     * or null if they have no values.
     *
     * @param value the object to be turned into a String
     * @return the string value of the object or null if the value is null
     *         or it is an array whose first value is null
     */
    public static String toString(Object value)
    {
        if (value instanceof String)
        {
            return (String)value;
        }
        if (value == null)
        {
            return null;
        }
        if (value.getClass().isArray())
        {
            if (Array.getLength(value) > 0)
            {
                // recurse on the first value
                return toString(Array.get(value, 0));
            }
            return null;
        }
        return String.valueOf(value);
    }

    /**
     * Returns the first value as a String, if any; otherwise returns null.
     *
     * @param values the Collection to be turned into a string
     * @return the string value of the first object in the collection
     *         or null if the collection is empty
     */
    public static String toString(Collection values)
    {
        if (values != null && !values.isEmpty())
        {
            // recurse on the first value
            return toString(values.iterator().next());
        }
        return null;
    }

    /**
     * Converts any Object to a boolean using {@link #toString(Object)}
     * and {@link Boolean#valueOf(String)}.
     *
     * @param value the object to be converted
     * @return a {@link Boolean} object for the specified value or
     *         <code>null</code> if the value is null or the conversion failed
     */
    public static Boolean toBoolean(Object value)
    {
        if (value instanceof Boolean)
        {
            return (Boolean)value;
        }

        String s = toString(value);
        return (s != null) ? Boolean.valueOf(s) : null;
    }

    /**
     * Converts a string to a {@link Locale}
     *
     * @param value - the string to parse
     * @return the {@link Locale} or <code>null</code> if the
     *         parsing fails
     */
    public static Locale toLocale(String value)
    {
        if (value.indexOf('_') < 0)
        {
            return new Locale(value);
        }

        String[] params = value.split("_");
        if (params.length == 2)
        {
            return new Locale(params[0], params[1]);
        }
        else if (params.length == 3)
        {
            return new Locale(params[0], params[1], params[2]);
        }
        else
        {
            // there's only 3 possible params, so this must be invalid
            return null;
        }
    }

    /**
     * Converts a string to a {@link URL}.  It will first try to
     * treat the string as a File name, then a classpath resource,
     * then finally as a literal URL.  If none of these work, then
     * this will return {@code null}.
     *
     * @param value - the string to parse
     * @return the {@link URL} form of the string or {@code null}
     * @see File
     * @see ClassUtils#getResource(String,Object)
     * @see URL
     */
    public static URL toURL(String value)
    {
        return toURL(value, ConversionUtils.class);
    }

    /**
     * Converts a string to a {@link URL}.  It will first try to
     * treat the string as a File name, then a classpath resource,
     * then finally as a literal URL.  If none of these work, then
     * this will return {@code null}.
     *
     * @param value - the string to parse
     * @param caller - the object or Class seeking the url
     * @return the {@link URL} form of the string or {@code null}
     * @see File
     * @see ClassUtils#getResource(String,Object)
     * @see URL
    */
    public static URL toURL(String value, Object caller)
    {
        try
        {
            File file = new File(value);
            if (file.exists())
            {
                return file.toURI().toURL();
            }
        }
        catch (Exception e) {}
        try
        {
            URL url = ClassUtils.getResource(value, caller);
            if (url != null)
            {
                return url;
            }
        }
        catch (Exception e) {}
        try
        {
            return new URL(value);
        }
        catch (Exception e) {}
        return null;
    }

    public static List asList(Object value)
    {
        if (value instanceof List) return (List)value;
        else if (value.getClass().isArray())
        {
            Class componentClass = value.getClass().getComponentType();
            if (componentClass.isPrimitive())
            {
                if (componentClass.equals(char.class)) value = ArrayUtils.toObject((char[])value);
                else if (componentClass.equals(long.class)) value = ArrayUtils.toObject((long[])value);
                else if (componentClass.equals(int.class)) value = ArrayUtils.toObject((int[])value);
                else if (componentClass.equals(short.class)) value = ArrayUtils.toObject((short[])value);
                else if (componentClass.equals(byte.class)) value = ArrayUtils.toObject((byte[])value);
                else if (componentClass.equals(double.class)) value = ArrayUtils.toObject((double[])value);
                else if (componentClass.equals(float.class)) value = ArrayUtils.toObject((float[])value);
            }
            return new ArrayList(Arrays.asList((Object[])value));
        }
        else
        {
            List ret = new ArrayList();
            ret.add(value);
            return ret;
        }
    }
}
