/*
 * Copyright (C) 2008 feilong
 *
 * Licensed 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.
 */
package com.feilong.core.bean;

import static com.feilong.core.Validator.isNullOrEmpty;
import static com.feilong.core.util.MapUtil.newLinkedHashMap;
import static com.feilong.core.util.SortUtil.sortMapByKeyAsc;
import static java.util.Collections.emptyMap;
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
import static org.apache.commons.lang3.StringUtils.EMPTY;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.ConvertUtilsBean;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.beanutils.converters.AbstractConverter;
import org.apache.commons.beanutils.converters.ArrayConverter;
import org.apache.commons.beanutils.converters.BigDecimalConverter;
import org.apache.commons.beanutils.converters.BigIntegerConverter;
import org.apache.commons.beanutils.converters.BooleanConverter;
import org.apache.commons.beanutils.converters.ByteConverter;
import org.apache.commons.beanutils.converters.CharacterConverter;
import org.apache.commons.beanutils.converters.DoubleConverter;
import org.apache.commons.beanutils.converters.FloatConverter;
import org.apache.commons.beanutils.converters.IntegerConverter;
import org.apache.commons.beanutils.converters.LongConverter;
import org.apache.commons.beanutils.converters.NumberConverter;
import org.apache.commons.beanutils.converters.ShortConverter;
import org.apache.commons.beanutils.converters.StringConverter;
import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;
import org.apache.commons.collections4.EnumerationUtils;
import org.apache.commons.collections4.IteratorUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.iterators.EnumerationIterator;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.LocaleUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.tuple.Pair;

import com.feilong.core.lang.ArrayUtil;
import com.feilong.core.lang.StringUtil;
import com.feilong.core.util.SortUtil;
import com.feilong.core.util.transformer.SimpleClassTransformer;

/**
 * 常用类型转换处理.
 * 
 * <h3>关于类型转换:</h3>
 * 
 * <blockquote>
 * <ul>
 * <li>{@link ConvertUtilsBean#registerPrimitives(boolean) registerPrimitives(boolean throwException)}</li>
 * <li>{@link ConvertUtilsBean#registerStandard(boolean,boolean) registerStandard(boolean throwException, boolean defaultNull);}</li>
 * <li>{@link ConvertUtilsBean#registerOther(boolean) registerOther(boolean throwException);}</li>
 * <li>{@link ConvertUtilsBean#registerArrays(boolean,int) registerArrays(boolean throwException, int defaultArraySize);}</li>
 * </ul>
 * </blockquote>
 * 
 * <h3>{@link ConvertUtils} 几个方法的区别:</h3>
 * 
 * <blockquote>
 * <table border="1" cellspacing="0" cellpadding="4" summary="">
 * <tr style="background-color:#ccccff">
 * <th align="left">方法</th>
 * <th align="left">说明</th>
 * </tr>
 * 
 * <tr valign="top">
 * <td>{@link ConvertUtils#convert(Object)}</td>
 * <td>将指定的value转成string.<br>
 * 如果value是array,将会返回数组第一个元素转成string.<br>
 * 将会使用注册的 <code>java.lang.String</code>{@link Converter},<br>
 * 允许应用定制 Object{@code ->}String conversions(默认使用简单的使用 toString())<br>
 * see {@link ConvertUtilsBean#convert(Object)}</td>
 * </tr>
 * 
 * <tr valign="top" style="background-color:#eeeeff">
 * <td>{@link ConvertUtils#convert(String, Class)}</td>
 * <td>将String value转成 指定Class 类型的对象 (如果可能),否则返回string.<br>
 * see {@link ConvertUtilsBean#convert(String, Class)}</td>
 * </tr>
 * 
 * <tr valign="top">
 * <td>{@link ConvertUtils#convert(String[], Class)}</td>
 * <td>将数组转成指定class类型的对象. <br>
 * 如果指定的Class类型是数组类型,那么返回值的类型将是数组的类型.否则将会构造一个指定类型的数组返回.<br>
 * see {@link ConvertUtilsBean#convert(String[], Class)} <br>
 * see {@link #toArray(String[], Class)}</td>
 * </tr>
 * 
 * <tr valign="top" style="background-color:#eeeeff">
 * <td>{@link ConvertUtils#convert(Object, Class)}</td>
 * <td>将value转成指定Class类型的对象,如果Class的转换器没有注册,那么传入的value原样返回.<br>
 * see {@link ConvertUtilsBean#convert(Object, Class)}<br>
 * see {@link #convert(Object, Class)}</td>
 * </tr>
 * 
 * </table>
 * </blockquote>
 * 
 * <p>
 * standard {@link Converter} instances are provided for all of the following destination Classes:
 * </p>
 * 
 * <blockquote>
 * <table border="1" cellspacing="0" cellpadding="4" summary="">
 * <tr style="background-color:#ccccff">
 * <th align="left">字段</th>
 * <th align="left">说明</th>
 * </tr>
 * 
 * <tr valign="top">
 * <td>{@link java.math.BigDecimal}</td>
 * <td><span style="color:red">no default value</span></td>
 * </tr>
 * 
 * <tr valign="top" style="background-color:#eeeeff">
 * <td>{@link java.math.BigInteger}</td>
 * <td><span style="color:red">no default value</span></td>
 * </tr>
 * 
 * <tr valign="top">
 * <td>boolean and {@link java.lang.Boolean}</td>
 * <td>default to false</td>
 * </tr>
 * 
 * <tr valign="top" style="background-color:#eeeeff">
 * <td>byte and {@link java.lang.Byte}</td>
 * <td>default to zero</td>
 * </tr>
 * 
 * <tr valign="top">
 * <td>char and {@link java.lang.Character}</td>
 * <td>default to a space</td>
 * </tr>
 * 
 * <tr valign="top" style="background-color:#eeeeff">
 * <td>{@link java.lang.Class}</td>
 * <td><span style="color:red">no default value</span></td>
 * </tr>
 * 
 * <tr valign="top">
 * <td>double and {@link java.lang.Double}</td>
 * <td>default to zero</td>
 * </tr>
 * 
 * <tr valign="top" style="background-color:#eeeeff">
 * <td>float and {@link java.lang.Float}</td>
 * <td>default to zero</td>
 * </tr>
 * 
 * <tr valign="top">
 * <td>int and {@link java.lang.Integer}</td>
 * <td>default to zero</td>
 * </tr>
 * 
 * <tr valign="top" style="background-color:#eeeeff">
 * <td>long and {@link java.lang.Long}</td>
 * <td>default to zero</td>
 * </tr>
 * 
 * <tr valign="top">
 * <td>short and {@link java.lang.Short}</td>
 * <td>default to zero</td>
 * </tr>
 * 
 * <tr valign="top" style="background-color:#eeeeff">
 * <td>{@link java.lang.String}</td>
 * <td>default to null</td>
 * </tr>
 * 
 * <tr valign="top">
 * <td>{@link java.io.File}</td>
 * <td><span style="color:red">no default value</span></td>
 * </tr>
 * 
 * <tr valign="top" style="background-color:#eeeeff">
 * <td>{@link java.net.URL}</td>
 * <td><span style="color:red">no default value</span></td>
 * </tr>
 * 
 * <tr valign="top">
 * <td>{@link java.sql.Date}</td>
 * <td><span style="color:red">no default value</span></td>
 * </tr>
 * 
 * <tr valign="top" style="background-color:#eeeeff">
 * <td>{@link java.sql.Time}</td>
 * <td><span style="color:red">no default value</span></td>
 * </tr>
 * 
 * <tr valign="top">
 * <td>{@link java.sql.Timestamp}</td>
 * <td><span style="color:red">no default value</span></td>
 * </tr>
 * </table>
 * </blockquote>
 * 
 * @author <a href="http://feitianbenyue.iteye.com/">feilong</a>
 * @see org.apache.commons.beanutils.ConvertUtils
 * @see org.apache.commons.beanutils.converters.AbstractConverter#handleMissing(Class)
 * @see org.apache.commons.beanutils.locale.LocaleConvertUtils
 * @since 1.3.0
 */
public final class ConvertUtil{

    /** Don't let anyone instantiate this class. */
    private ConvertUtil(){
        //AssertionError不是必须的. 但它可以避免不小心在类的内部调用构造器. 保证该类在任何情况下都不会被实例化.
        //see 《Effective Java》 2nd
        throw new AssertionError("No " + getClass().getName() + " instances for you!");
    }

    //---------------------------------------------------------------

    static{
        //初始化注册器.
        ConvertUtil.registerStandardDefaultNull();
    }

    //---------------------------------------------------------------

    /**
     * Register standard default null.
     * 
     * @see ConvertUtilsBean#registerPrimitives(boolean) registerPrimitives(boolean throwException)
     * @see ConvertUtilsBean#registerStandard(boolean,boolean) registerStandard(boolean throwException, boolean defaultNull)
     * @see ConvertUtilsBean#registerOther(boolean) registerOther(boolean throwException)
     * @see ConvertUtilsBean#registerArrays(boolean,int) registerArrays(boolean throwException, int defaultArraySize)
     * @see ConvertUtilsBean#deregister(Class) ConvertUtilsBean.deregister(Class)
     * @since 1.11.2
     */
    public static void registerStandardDefaultNull(){
        ConvertUtils.register(new BigDecimalConverter(null), BigDecimal.class);
        ConvertUtils.register(new BigIntegerConverter(null), BigInteger.class);
        ConvertUtils.register(new BooleanConverter(null), Boolean.class);
        ConvertUtils.register(new ByteConverter(null), Byte.class);
        ConvertUtils.register(new CharacterConverter(null), Character.class);
        ConvertUtils.register(new DoubleConverter(null), Double.class);
        ConvertUtils.register(new FloatConverter(null), Float.class);
        ConvertUtils.register(new IntegerConverter(null), Integer.class);
        ConvertUtils.register(new LongConverter(null), Long.class);
        ConvertUtils.register(new ShortConverter(null), Short.class);
        ConvertUtils.register(new StringConverter(null), String.class);
    }

    //---------------------------------------------------------------

    /**
     * Register simple date locale converter.
     *
     * @param pattern
     *            the pattern
     * @since 1.11.2
     */
    public static void registerSimpleDateLocaleConverter(String pattern){
        DateLocaleConverter dateLocaleConverter = new DateLocaleConverter(null, Locale.getDefault(), pattern);
        ConvertUtils.register(dateLocaleConverter, Date.class);
    }

    //---------------------toBoolean------------------------------------------

    /**
     * 将 <code>toBeConvertedValue</code> 转换成 {@link Boolean}类型.
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * 
     * ConvertUtil.toBoolean(null)      =   null
     * 
     * ConvertUtil.toBoolean(1L)        =   true
     * ConvertUtil.toBoolean("1")       =   true
     * ConvertUtil.toBoolean("9")       =   null
     * ConvertUtil.toBoolean("1,2,3")   =   null
     * </pre>
     * 
     * </blockquote>
     * 
     * <h3>逻辑及规则:</h3>
     * 
     * <blockquote>
     * 
     * <ul>
     * <li>如果 "true", "yes", "y", "on", "1" <span style="color:green">(忽视大小写)</span>, 返回 true</li>
     * <li>如果 "false", "no", "n", "off", "0" <span style="color:green">(忽视大小写)</span>, 返回 false</li>
     * <li>其他抛出 conversionException, 但是在
     * {@link org.apache.commons.beanutils.converters.AbstractConverter#handleError(Class, Object, Throwable) handleError(Class, Object,
     * Throwable)} 方法里面返回默认值 是 null
     * </ul>
     * 
     * <p>
     * 你也可以调用 {@link org.apache.commons.beanutils.converters.BooleanConverter#BooleanConverter(String[], String[], Object)
     * BooleanConverter(String[], String[], Object)} 设置 trueStrings 和 falseStrings
     * </p>
     * </blockquote>
     * 
     * <h3>和 {@link Boolean#parseBoolean(String)}的区别:</h3>
     * 
     * <blockquote>
     * <p>
     * {@link Boolean#parseBoolean(String)},仅当 <code>(String != null) 并且 String.equalsIgnoreCase("true")</code> 返回 true
     * </p>
     * </blockquote>
     * 
     * @param toBeConvertedValue
     *            object
     * @return 如果 <code>toBeConvertedValue</code> 是null,返回null<br>
     * @see #convert(Object, Class)
     * @see org.apache.commons.beanutils.converters.BooleanConverter
     * @see org.apache.commons.lang3.BooleanUtils
     * @see java.lang.Boolean#parseBoolean(String)
     */
    public static Boolean toBoolean(Object toBeConvertedValue){
        return new BooleanConverter(null).convert(Boolean.class, toBeConvertedValue);
    }

    //----------------------toInteger-----------------------------------------

    /**
     * 将 <code>toBeConvertedValue</code> 转换成 {@link Integer}类型.
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * 
     * ConvertUtil.toInteger(null)                  = null
     * ConvertUtil.toInteger("aaaa")                = null
     * ConvertUtil.toInteger(8L)                    = 8
     * ConvertUtil.toInteger("8")                   = 8
     * ConvertUtil.toInteger(new BigDecimal("8"))   = 8
     * </pre>
     * 
     * <p>
     * 如果传入的参数 <code>toBeConvertedValue</code> 是 <b>数组</b>,那么<b>取第一个元素</b>进行转换,参见 {@link AbstractConverter#convertArray(Object)} L227:
     * </p>
     * 
     * <pre class="code">
     * ConvertUtil.toInteger(new String[] { "1", "2", "3" }) = 1
     * </pre>
     * 
     * <p>
     * 如果传入的参数 <code>toBeConvertedValue</code> 是 <b>集合</b>,那么<b>取第一个元素</b>进行转换,参见 {@link AbstractConverter#convertArray(Object)} Line234:
     * </p>
     * 
     * <pre class="code">
     * ConvertUtil.toInteger(toList("1", "2")) = 1
     * </pre>
     * 
     * </blockquote>
     * 
     * <p>
     * 该方法非常适用 获取request请求的分页参数
     * </p>
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <p>
     * 原来的写法:
     * </p>
     * 
     * <pre class="code">
     * 
     * public static Integer getCurrentPageNo(HttpServletRequest request,String pageParamName){
     *     String pageNoString = RequestUtil.getParameter(request, pageParamName);
     *     try{
     *         int pageNo = Integer.parseInt(pageNoString);
     *         return pageNo;
     *     }catch (Exception e){
     *         LOGGER.error(e.getClass().getName(), e);
     *     }
     *     return 1; <span style="color:green">// 不带这个参数或者转换异常返回1</span>
     * }
     * 
     * </pre>
     * 
     * <p>
     * 现在可以更改成:
     * </p>
     * 
     * <pre class="code">
     * 
     * public static Integer getCurrentPageNo(HttpServletRequest request,String pageParamName){
     *     String pageNoString = RequestUtil.getParameter(request, pageParamName);
     *     Integer pageNo = ConvertUtil.toInteger(pageNoString);
     *     return null == pageNo ? 1 : pageNo;
     * }
     * </pre>
     * 
     * <p>
     * 当然对于这种场景,最快捷的:调用支持默认值的 {@link #toInteger(Object, Integer)} 方法
     * </p>
     * 
     * <pre class="code">
     * 
     * public static Integer getCurrentPageNo(HttpServletRequest request,String pageParamName){
     *     String pageNoString = RequestUtil.getParameter(request, pageParamName);
     *     return ConvertUtil.toInteger(pageNoString, 1);
     * }
     * </pre>
     * 
     * </blockquote>
     *
     * @param toBeConvertedValue
     *            值
     * @return 如果 <code>toBeConvertedValue</code> 是null,返回 null<br>
     *         如果传入的参数 <code>toBeConvertedValue</code> 是 <b>数组</b>,那么<b>取第一个元素</b>进行转换<br>
     *         如果传入的参数 <code>toBeConvertedValue</code> 是 <b>集合</b>,那么<b>取第一个元素</b>进行转换<br>
     *         如果找不到转换器或者转换的时候出现了异常,返回 null
     * @see org.apache.commons.beanutils.converters.IntegerConverter
     * @see org.apache.commons.lang3.math.NumberUtils#toInt(String)
     * @see #toInteger(Object, Integer)
     */
    public static Integer toInteger(Object toBeConvertedValue){
        return toInteger(toBeConvertedValue, null);
    }

    /**
     * 将 <code>toBeConvertedValue</code> 转换成 {@link Integer}类型,如果转换不了返回默认值 <code>defaultValue</code>.
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * ConvertUtil.toInteger(null,null)               = null
     * ConvertUtil.toInteger(null,1)                  = 1
     * ConvertUtil.toInteger("aaaa",1)                = 1
     * ConvertUtil.toInteger(8L,1)                    = 8
     * ConvertUtil.toInteger("8",1)                   = 8
     * ConvertUtil.toInteger(new BigDecimal("8"),1)   = 8
     * </pre>
     * 
     * <p>
     * 如果传入的参数 <code>toBeConvertedValue</code> 是 <b>数组</b>,那么<b>取第一个元素</b>进行转换,参见 {@link AbstractConverter#convertArray(Object)} L227:
     * </p>
     * 
     * <pre class="code">
     * ConvertUtil.toInteger(new String[] { "1", "2", "3" }, 8) = 1
     * </pre>
     * 
     * <p>
     * 如果传入的参数 <code>toBeConvertedValue</code> 是 <b>集合</b>,那么<b>取第一个元素</b>进行转换,参见 {@link AbstractConverter#convertArray(Object)} Line234:
     * </p>
     * 
     * <pre class="code">
     * ConvertUtil.toInteger(toList("1", "2"), 8) = 1
     * </pre>
     * 
     * </blockquote>
     * 
     * <p>
     * 该方法非常适用 获取request请求的分页参数
     * </p>
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * 原来的写法:
     * 
     * <pre class="code">
     * 
     * public static Integer getCurrentPageNo(HttpServletRequest request,String pageParamName){
     *     String pageNoString = RequestUtil.getParameter(request, pageParamName);
     *     try{
     *         int pageNo = Integer.parseInt(pageNoString);
     *         return pageNo;
     *     }catch (Exception e){
     *         LOGGER.error(e.getClass().getName(), e);
     *     }
     *     return 1; <span style="color:green">// 不带这个参数或者转换异常返回1</span>
     * }
     * 
     * </pre>
     * 
     * 现在可以更改成:
     * 
     * <pre class="code">
     * 
     * public static Integer getCurrentPageNo(HttpServletRequest request,String pageParamName){
     *     String pageNoString = RequestUtil.getParameter(request, pageParamName);
     *     return ConvertUtil.toInteger(pageNoString, 1);
     * }
     * </pre>
     * 
     * </blockquote>
     *
     * @param toBeConvertedValue
     *            值
     * @param defaultValue
     *            默认值
     * @return 如果 <code>toBeConvertedValue</code> 是null,返回 <code>defaultValue</code> <br>
     *         如果传入的参数 <code>toBeConvertedValue</code> 是 <b>数组</b>,那么<b>取第一个元素</b>进行转换<br>
     *         如果传入的参数 <code>toBeConvertedValue</code> 是 <b>集合</b>,那么<b>取第一个元素</b>进行转换<br>
     *         如果找不到转换器或者转换的时候出现了异常,返回 <code>defaultValue</code>
     * @see org.apache.commons.beanutils.converters.IntegerConverter
     * @see org.apache.commons.lang3.ObjectUtils#defaultIfNull(Object, Object)
     * @since 1.6.1
     */
    public static Integer toInteger(Object toBeConvertedValue,Integer defaultValue){
        return new IntegerConverter(defaultValue).convert(Integer.class, toBeConvertedValue);
    }

    //------------------------toLong---------------------------------------

    /**
     * 将 <code>toBeConvertedValue</code> 转换成 {@link Long}类型.
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * ConvertUtil.toLong(null)                     = null
     * ConvertUtil.toLong("aaaa")                   = null
     * ConvertUtil.toLong(8)                        = 8L
     * ConvertUtil.toLong("8")                      = 8L
     * ConvertUtil.toLong(new BigDecimal("8"))      = 8L
     * </pre>
     * 
     * <p>
     * 如果传入的参数 <code>toBeConvertedValue</code> 是 <b>数组</b>,那么<b>取第一个元素</b>进行转换,参见 {@link AbstractConverter#convertArray(Object)} L227:
     * </p>
     * 
     * <pre class="code">
     * ConvertUtil.toLong(new String[] { "1", "2", "3" }) = 1L
     * </pre>
     * 
     * <p>
     * 如果传入的参数 <code>toBeConvertedValue</code> 是 <b>集合</b>,那么<b>取第一个元素</b>进行转换,参见 {@link AbstractConverter#convertArray(Object)} Line234:
     * </p>
     * 
     * <pre class="code">
     * ConvertUtil.toLong(toList("1", "2")) = 1L
     * </pre>
     * 
     * </blockquote>
     * 
     * @param toBeConvertedValue
     *            包含数字的对象.
     * @return 如果 <code>toBeConvertedValue</code> 是null,返回 null<br>
     *         如果传入的参数 <code>toBeConvertedValue</code> 是 <b>数组</b>,那么<b>取第一个元素</b>进行转换<br>
     *         如果传入的参数 <code>toBeConvertedValue</code> 是 <b>集合</b>,那么<b>取第一个元素</b>进行转换<br>
     *         如果找不到转换器或者转换的时候出现了异常,返回 null
     * @see #convert(Object, Class)
     * @see org.apache.commons.beanutils.converters.LongConverter
     * @see org.apache.commons.lang3.math.NumberUtils#toLong(String)
     */
    public static Long toLong(Object toBeConvertedValue){
        return new LongConverter(null).convert(Long.class, toBeConvertedValue);
    }

    //------------------------toBigDecimal---------------------------------------

    /**
     * 将 <code>toBeConvertedValue</code> 转换成 {@link java.math.BigDecimal}.
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * ConvertUtil.toBigDecimal(null)                     = null
     * ConvertUtil.toBigDecimal("aaaa")                   = null
     * ConvertUtil.toBigDecimal(8)                        = BigDecimal.valueOf(8)
     * ConvertUtil.toBigDecimal("8")                      = BigDecimal.valueOf(8)
     * ConvertUtil.toBigDecimal(new BigDecimal("8"))      = BigDecimal.valueOf(8)
     * </pre>
     * 
     * <p>
     * 如果传入的参数 <code>toBeConvertedValue</code> 是 <b>数组</b>,那么<b>取第一个元素</b>进行转换,参见 {@link AbstractConverter#convertArray(Object)} L227:
     * </p>
     * 
     * <pre class="code">
     * ConvertUtil.toBigDecimal(new String[] { "1", "2", "3" }) = BigDecimal.valueOf(1)
     * </pre>
     * 
     * <p>
     * 如果传入的参数 <code>toBeConvertedValue</code> 是 <b>集合</b>,那么<b>取第一个元素</b>进行转换,参见 {@link AbstractConverter#convertArray(Object)} Line234:
     * </p>
     * 
     * <pre class="code">
     * ConvertUtil.toBigDecimal(toList("1", "2")) = BigDecimal.valueOf(1)
     * </pre>
     * 
     * </blockquote>
     * 
     * <h3>{@link java.lang.Double} 转成 {@link java.math.BigDecimal}注意点:</h3>
     * 
     * <blockquote>
     * 
     * <p>
     * <span style="color:red">推荐使用 {@link BigDecimal#valueOf(double)}</span>,不建议使用 <code>new BigDecimal(double)</code>,参见 JDK API<br>
     * </p>
     * 
     * <ul>
     * <li>{@code new BigDecimal(0.1) ====> 0.1000000000000000055511151231257827021181583404541015625}</li>
     * <li>{@code BigDecimal.valueOf(0.1) ====> 0.1}</li>
     * </ul>
     * 
     * <p>
     * 本方法底层调用的是 {@link NumberConverter#toNumber(Class, Class, Number)
     * NumberConverter#toNumber(Class, Class, Number)},正确的处理了 {@link java.lang.Double} 转成 {@link java.math.BigDecimal}
     * </p>
     * </blockquote>
     * 
     * @param toBeConvertedValue
     *            值
     * @return 如果 <code>toBeConvertedValue</code> 是null,返回 null<br>
     *         如果传入的参数 <code>toBeConvertedValue</code> 是 <b>数组</b>,那么<b>取第一个元素</b>进行转换<br>
     *         如果传入的参数 <code>toBeConvertedValue</code> 是 <b>集合</b>,那么<b>取第一个元素</b>进行转换<br>
     *         如果找不到转换器或者转换的时候出现了异常,返回 null
     * @see #convert(Object, Class)
     * @see org.apache.commons.beanutils.converters.NumberConverter#toNumber(Class, Class, Number)
     * @see org.apache.commons.beanutils.converters.BigDecimalConverter
     */
    public static BigDecimal toBigDecimal(Object toBeConvertedValue){
        return new BigDecimalConverter(null).convert(BigDecimal.class, toBeConvertedValue);
    }

    //---------------------------------------------------------------
    //数组

    /**
     * 将 <code>toBeConvertedValue</code> 转成{@link Integer} 数组.
     * 
     * <h3>说明:</h3>
     * <blockquote>
     * 
     * <p>
     * 核心实现,参见 {@link ArrayConverter#convertToType(Class, Object)}
     * </p>
     * 
     * <dl>
     * <dt>如果参数 <code>toBeConvertedValue</code>是 <code>数组</code> 或者 {@link Collection}</dt>
     * 
     * <dd>
     * <p>
     * 参见{@link org.apache.commons.beanutils.converters.ArrayConverter#convertToType(Class, Object)
     * ArrayConverter#convertToType(Class,Object)}<br>
     * 
     * 会构造一个<code>Integer</code>数组,长度就是 <code>toBeConvertedValue</code>的大小或者长度,然后迭代<code>toBeConvertedValue</code>依次逐个进行转换
     * </p>
     * 
     * <h4>示例:</h4>
     * 
     * <pre class="code">
     * ConvertUtil.toIntegers(new String[] { "1", "2", "3" })       = [1,2,3]
     * ConvertUtil.toIntegers(toList("1", "2", "3"))    = [1,2,3]
     * </pre>
     * 
     * </dd>
     * 
     * <dt>如果参数 <code>toBeConvertedValue</code>不是<code>数组</code>也不是{@link Collection}</dt>
     * 
     * <dd>
     * <p>
     * 那么首先会调用 {@link ArrayConverter#convertToCollection(Class, Object)} 将 <code>toBeConvertedValue</code>转成集合,转换逻辑参见
     * {@link ArrayConverter#convertToCollection(Class, Object)}:
     * </p>
     * 
     * <ol>
     * <li>如果 <code>toBeConvertedValue</code>是{@link Number}, {@link Boolean} 或者 {@link java.util.Date} ,那么构造只有一个
     * <code>toBeConvertedValue</code> 元素的 List返回.</li>
     * <li>其他类型将转成字符串,然后调用 {@link ArrayConverter#parseElements(Class, String)}转成list.
     * 
     * <p>
     * 具体转换逻辑为:
     * </p>
     * 
     * <ul>
     * <li>字符串期望是一个逗号分隔的字符串.</li>
     * <li>字符串可以被'{' 开头 和 '}'结尾的分隔符包裹,程序内部会自动截取.</li>
     * <li>会去除前后空白.</li>
     * <li>Elements in the list may be delimited by single or double quotes. Within a quoted elements, the normal Java escape sequences are
     * valid.</li>
     * </ul>
     * 
     * </li>
     * </ol>
     * 
     * <p>
     * 得到list之后,会构造一个<code>Integer</code>数组,长度就是 <code>toBeConvertedValue</code>的大小或者长度,然后迭代<code>toBeConvertedValue</code>依次逐个进行转换
     * </p>
     * 
     * <h4>示例:</h4>
     * 
     * <pre class="code">
     * ConvertUtil.toIntegers("1,2,3")                  = new Integer[] { 1, 2, 3 }
     * ConvertUtil.toIntegers("{1,2,3}")                = new Integer[] { 1, 2, 3 }
     * ConvertUtil.toIntegers("{ 1 ,2,3}")              = new Integer[] { 1, 2, 3 }
     * ConvertUtil.toIntegers("1,2, 3")                 = new Integer[] { 1, 2, 3 }
     * ConvertUtil.toIntegers("1,2 , 3")                = new Integer[] { 1, 2, 3 }
     * </pre>
     * 
     * </dd>
     * 
     * </dl>
     * 
     * <p>
     * 每个元素转换成 Integer的时候,会调用
     * {@link org.apache.commons.beanutils.converters.NumberConverter#convertToType(Class, Object)},具体的规则是:
     * </p>
     * 
     * <blockquote>
     * 
     * <dl>
     * <dt>1.如果 元素是 Number类型</dt>
     * <dd>那么会调用 {@link org.apache.commons.beanutils.converters.NumberConverter#toNumber(Class, Class, Number)}</dd>
     * 
     * <dt>2.如果 元素是 Boolean类型</dt>
     * <dd>那么 true被转成1,false 转成 0</dd>
     * 
     * <dt>3.其他情况</dt>
     * <dd>将元素转成字符串,并trim,再进行转换</dd>
     * 
     * <dt>4.元素是null的情况</dt>
     * <dd>如果有元素是null,那么会调用 {@link org.apache.commons.beanutils.converters.AbstractConverter#convert(Class, Object)},会调用
     * {@link org.apache.commons.beanutils.converters.AbstractConverter#handleMissing(Class)} 方法,没有默认值的话,会抛出异常,然后catch之后返回 empty Integer 数组
     * </dd>
     * </dl>
     * 
     * <h4>示例:</h4>
     * 
     * <pre class="code">
     * ConvertUtil.toIntegers(toList("1", "2", <span style="color:red">" 3"</span>))        = new Integer[] { 1, 2, 3 }
     * ConvertUtil.toIntegers(toArray(true, false, false))                                  = new Integer[] { 1, 0, 0 }
     * ConvertUtil.toIntegers(new String[] { "1", null, "2", "3" })                         = new Integer[] {}
     * </pre>
     * 
     * </blockquote>
     * 
     * </blockquote>
     * 
     * @param toBeConvertedValue
     *            需要被转换的值
     * @return 如果 <code>toBeConvertedValue</code> 是null,返回 null<br>
     * @see #convert(Object, Class)
     * @see org.apache.commons.beanutils.converters.ArrayConverter
     */
    public static Integer[] toIntegers(Object toBeConvertedValue){
        return convert(toBeConvertedValue, Integer[].class);
    }

    /**
     * 将 <code>toBeConvertedValue</code> 转成Long 数组.
     * 
     * <h3>说明:</h3>
     * <blockquote>
     * 
     * <p>
     * 核心实现,参见 {@link ArrayConverter#convertToType(Class, Object)}
     * </p>
     * 
     * <dl>
     * <dt>如果参数 <code>toBeConvertedValue</code>是 <code>数组</code> 或者 {@link Collection}</dt>
     * 
     * <dd>
     * <p>
     * 参见{@link org.apache.commons.beanutils.converters.ArrayConverter#convertToType(Class, Object)
     * ArrayConverter#convertToType(Class,Object)}<br>
     * 
     * 会构造一个<code>Long</code>数组,长度就是 <code>toBeConvertedValue</code>的大小或者长度,然后迭代<code>toBeConvertedValue</code>依次逐个进行转换
     * </p>
     * 
     * <h4>示例:</h4>
     * 
     * <pre class="code">
     * ConvertUtil.toLongs(new String[] { "1", "2", "3" }       = [1L,2L,3L]
     * ConvertUtil.toLongs(toList("1", "2", "3"))               = [1L,2L,3L]
     * </pre>
     * 
     * </dd>
     * 
     * <dt>如果参数 <code>toBeConvertedValue</code>不是<code>数组</code>也不是{@link Collection}</dt>
     * 
     * <dd>
     * <p>
     * 那么首先会调用 {@link ArrayConverter#convertToCollection(Class, Object)} 将 <code>toBeConvertedValue</code>转成集合,转换逻辑参见
     * {@link ArrayConverter#convertToCollection(Class, Object)}:
     * </p>
     * 
     * <ol>
     * <li>如果 <code>toBeConvertedValue</code>是{@link Number}, {@link Boolean} 或者 {@link java.util.Date} ,那么构造只有一个
     * <code>toBeConvertedValue</code> 元素的 List返回.</li>
     * <li>其他类型将转成字符串,然后调用 {@link ArrayConverter#parseElements(Class, String)}转成list.
     * 
     * <p>
     * 具体转换逻辑为:
     * </p>
     * 
     * <ul>
     * <li>字符串期望是一个逗号分隔的字符串.</li>
     * <li>字符串可以被'{' 开头 和 '}'结尾的分隔符包裹,程序内部会自动截取.</li>
     * <li>会去除前后空白.</li>
     * <li>Elements in the list may be delimited by single or double quotes. Within a quoted elements, the normal Java escape sequences are
     * valid.</li>
     * </ul>
     * 
     * </li>
     * </ol>
     * 
     * <p>
     * 得到list之后,会构造一个<code>Long</code>数组,长度就是 <code>toBeConvertedValue</code>的大小或者长度,然后迭代<code>toBeConvertedValue</code>依次逐个进行转换
     * </p>
     * 
     * <h4>示例:</h4>
     * 
     * <pre class="code">
     * ConvertUtil.toLongs("1,2,3")                  = new Long[] { 1L, 2L, 3L }
     * ConvertUtil.toLongs("{1,2,3}")                = new Long[] { 1L, 2L, 3L }
     * ConvertUtil.toLongs("{ 1 ,2,3}")              = new Long[] { 1L, 2L, 3L }
     * ConvertUtil.toLongs("1,2, 3")                 = new Long[] { 1L, 2L, 3L }
     * ConvertUtil.toLongs("1,2 , 3")                = new Long[] { 1L, 2L, 3L }
     * </pre>
     * 
     * </dd>
     * 
     * </dl>
     * 
     * <p>
     * 每个元素转换成 Integer的时候,会调用
     * {@link org.apache.commons.beanutils.converters.NumberConverter#convertToType(Class, Object)},具体的规则是:
     * </p>
     * 
     * <blockquote>
     * 
     * <dl>
     * <dt>1.如果 元素是 Number类型</dt>
     * <dd>那么会调用 {@link org.apache.commons.beanutils.converters.NumberConverter#toNumber(Class, Class, Number)}</dd>
     * 
     * <dt>2.如果 元素是 Boolean类型</dt>
     * <dd>那么 true被转成1L,false 转成 0L</dd>
     * 
     * <dt>3.其他情况</dt>
     * <dd>将元素转成字符串,并trim,再进行转换</dd>
     * 
     * <dt>4.元素是null的情况</dt>
     * <dd>如果有元素是null,那么会调用 {@link org.apache.commons.beanutils.converters.AbstractConverter#convert(Class, Object)},会调用
     * {@link org.apache.commons.beanutils.converters.AbstractConverter#handleMissing(Class)} 方法,没有默认值的话,会抛出异常,然后catch之后返回 empty Integer 数组
     * </dd>
     * </dl>
     * 
     * <h4>示例:</h4>
     * 
     * <pre class="code">
     * ConvertUtil.toLongs(toList("1", "2", <span style="color:red">" 3"</span>))        = new Long[] { 1L, 2L, 3L }
     * ConvertUtil.toLongs(toArray(true, false, false))                                  = new Long[] { 1L, 0L, 0L }
     * ConvertUtil.toLongs(new String[] { "1", null, "2", "3" })                         = new Long[] {}
     * </pre>
     * 
     * </blockquote>
     * 
     * </blockquote>
     * 
     * <h3>特别适合以下形式的代码:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * 
     * protected long[] getOrderIdLongs(String orderIds){
     *     <span style="color:green">// 确认交易时候插入数据库的时候,不应该会出现空的情况</span>
     *     String[] orderIdArray = orderIds.split(",");
     *     int orderLength = orderIdArray.length;
     *     long[] ids = new long[orderLength];
     *     for (int i = 0, j = orderLength; i {@code <} j; ++i){
     *         ids[i] = Long.parseLong(orderIdArray[i]);
     *     }
     *     return ids;
     * }
     * 
     * </pre>
     * 
     * <b>可以重构成:</b>
     * 
     * <pre class="code">
     * 
     * protected long[] getOrderIdLongs(String orderIds){
     *     return toLongs(orderIds);
     * }
     * </pre>
     * 
     * </blockquote>
     * 
     * @param toBeConvertedValue
     *            the to be converted value
     * @return 如果 <code>toBeConvertedValue</code> 是null,返回 null<br>
     * @see org.apache.commons.beanutils.ConvertUtils#convert(Object, Class)
     * @see org.apache.commons.beanutils.converters.ArrayConverter
     * @see #convert(Object, Class)
     */
    public static Long[] toLongs(Object toBeConvertedValue){
        return convert(toBeConvertedValue, Long[].class);
    }

    //---------------------------------------------------------------

    /**
     * 把对象 <code>toBeConvertedValue</code> 转换成字符串.
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * ConvertUtil.toString(1)                  =   "1"
     * ConvertUtil.toString(toLong(8L))         =   "8"
     * ConvertUtil.toString(toBigDecimal(1.0))  =   "1.00"
     * ConvertUtil.toString(new Double(1.0))  =   "1.00"
     * ConvertUtil.toString(new Float(1.0))  =   "1.00"
     * 
     * ConvertUtil.toString(toList("张飞", "关羽", "", "赵云"))  =   "张飞,关羽,,赵云"
     * ConvertUtil.toString(toArray("张飞", "关羽", "", "赵云"))  =   "张飞,关羽,,赵云"
     * ConvertUtil.toString(toArray(null, "关羽", "", "赵云"))  =   ",关羽,,赵云"
     * </pre>
     * 
     * </blockquote>
     * 
     * @param toBeConvertedValue
     *            参数值
     * @return 如果 <code>toBeConvertedValue</code> 是null,返回 null<br>
     *         如果 <code>toBeConvertedValue</code> 是 {@link CharSequence},直接 toString返回<br>
     *         如果 <code>toBeConvertedValue</code> 是 数组,那么调用 {@link ConvertUtil#toString(Object[], String)}<br>
     *         如果 <code>toBeConvertedValue</code> 是 {@link Collection},那么调用 {@link ConvertUtil#toString(Object[], String)}<br>
     *         如果 <code>toBeConvertedValue</code> 是 {@link Date},那么返回 {@link com.feilong.core.DatePattern#COMMON_DATE_AND_TIME} 格式字符串<br>
     *         如果 <code>toBeConvertedValue</code> 是 {@link BigDecimal}或者是{@link Float}或者是 {@link Double},那么返回
     *         {@link com.feilong.core.NumberPattern#TWO_DECIMAL_POINTS} 2 位小数点格式字符串<br>
     *         其他调用 {@link com.feilong.core.bean.ConvertUtil#convert(Object, Class)}
     * @see org.apache.commons.beanutils.converters.ArrayConverter#convertToString(Object)
     * @see org.apache.commons.beanutils.ConvertUtils#convert(Object)
     * @see org.apache.commons.beanutils.ConvertUtilsBean#convert(Object)
     * @see org.apache.commons.beanutils.converters.StringConverter
     * 
     * @see java.util.Arrays#toString(Object[])
     * @since 1.14.0 call {@link com.feilong.core.bean.ToStringHandler#toStringValue(Object)}
     */
    public static String toString(Object toBeConvertedValue){
        return ToStringHandler.toStringValue(toBeConvertedValue);
    }

    //---------------------------------------------------------------

    /**
     * 将集合 <code>collection</code> 使用拼接 <code>connector</code> 拼接成字符串.
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * List{@code <String>} list = com.feilong.core.bean.ConvertUtil.toList("feilong", "", "xinge");
     * ConvertUtil.toString(list,",");
     * </pre>
     * 
     * <b>输出:</b>
     * 
     * <pre class="code">
     * feilong,,xinge
     * </pre>
     * 
     * <hr>
     * 
     * 你还可以使用这个方法来将集合<b>换行输出</b>,比如:
     * 
     * <pre class="code">
     * List{@code <String>} list = toList("飞龙", "小金", "四金", "金金金金");
     * 
     * LOGGER.debug(ConvertUtil.toString(list, System.lineSeparator()));
     * </pre>
     * 
     * <b>输出:</b>
     * 
     * <pre class="code">
     * 飞龙
     * 小金
     * 四金
     * 金金金金
     * </pre>
     * 
     * </blockquote>
     * 
     * <h3>说明</h3>
     * <blockquote>
     * 
     * <ol>
     * <li>如果有元素是null,使用{@link StringUtils#EMPTY}替代拼接</li>
     * <li>最后一个元素后面不拼接拼接符</li>
     * </ol>
     * </blockquote>
     *
     * @param collection
     *            集合,建议元素泛型不要使用自定义的对象(比如UserCommand等),因为这个方法是迭代collection,拿每个元素的字符串格式 进行拼接
     * @param connector
     *            the connector
     * @return 如果 <code>collection</code> 是null或者empty,返回 {@link StringUtils#EMPTY}<br>
     * @see "org.springframework.util.StringUtils#collectionToDelimitedString(Collection, String, String, String)"
     * @see org.apache.commons.collections4.IteratorUtils#toString(Iterator)
     * @see org.apache.commons.lang3.StringUtils#join(Iterable, String)
     * @since 1.11.0
     */
    public static String toString(final Collection<?> collection,String connector){
        return isNullOrEmpty(collection) ? EMPTY : //
                        toString(collection.toArray(), new ToStringConfig(connector));
    }

    /**
     * 将数组 <code>arrays</code> 通过 <code>connector</code> 拼接成字符串.
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * ConvertUtil.toString(null,",")               =   ""
     * ConvertUtil.toString(toArray(),",")          =   ""
     * 
     * ConvertUtil.toString(toArray("a","b"),",")   =   "a,b"
     * 
     * Integer[] array3 = { 2, null, 1, null };
     * ConvertUtil.toString(array3,",")             =   "2,,1,"
     * </pre>
     * 
     * </blockquote>
     * 
     * <h3>如果原始类型数组需要转换:</h3>
     * <blockquote>
     * 
     * <p>
     * 需要先使用下列的方式先转成包装类型数组
     * </p>
     * 
     * <ol>
     * <li>{@link ArrayUtils#toObject(boolean[])}</li>
     * <li>{@link ArrayUtils#toObject(byte[])}</li>
     * <li>{@link ArrayUtils#toObject(char[])}</li>
     * <li>{@link ArrayUtils#toObject(double[])}</li>
     * <li>{@link ArrayUtils#toObject(float[])}</li>
     * <li>{@link ArrayUtils#toObject(int[])}</li>
     * <li>{@link ArrayUtils#toObject(long[])}</li>
     * <li>{@link ArrayUtils#toObject(short[])}</li>
     * </ol>
     * </blockquote>
     * 
     * <h3>说明</h3>
     * <blockquote>
     * 
     * <ol>
     * <li>如果有元素是null,使用{@link StringUtils#EMPTY}替代拼接</li>
     * <li>最后一个元素后面不拼接拼接符</li>
     * </ol>
     * </blockquote>
     *
     * @param arrays
     *            支持包装类型,<b>不直接支持</b>原始类型
     * @param connector
     *            the connector
     * @return 如果 <code>arrays</code> 是null 或者Empty,返回 {@link StringUtils#EMPTY}<br>
     * @see org.apache.commons.lang3.builder.ToStringStyle
     * @see org.apache.commons.lang3.StringUtils#join(Object[], String)
     * @since 1.11.0
     */
    public static String toString(Object[] arrays,String connector){
        return isNullOrEmpty(arrays) ? EMPTY : toString(arrays, new ToStringConfig(connector));
    }

    //---------------------------------------------------------------

    // toString use ToStringConfig

    /**
     * 将集合 <code>collection</code> 使用拼接配置 toStringConfig 拼接成字符串.
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * List{@code <String>} list = new ArrayList{@code <>}();
     * list.add("feilong");
     * list.add("");
     * list.add("xinge");
     * 
     * ToStringConfig toStringConfig = new ToStringConfig(",");
     * toStringConfig.setIsJoinNullOrEmpty(false);
     * 
     * ConvertUtil.toString(list,toStringConfig);
     * </pre>
     * 
     * <b>输出:</b>
     * 
     * <pre class="code">
     * feilong,xinge
     * </pre>
     * 
     * <hr>
     * 
     * 你还可以使用这个方法来将集合<b>换行输出</b>,比如:
     * 
     * <pre class="code">
     * List{@code <String>} list = toList("飞龙", "小金", "四金", "金金金金");
     * 
     * ToStringConfig toStringConfig = new ToStringConfig(System.lineSeparator());
     * LOGGER.debug(ConvertUtil.toString(list, toStringConfig));
     * </pre>
     * 
     * <b>输出:</b>
     * 
     * <pre class="code">
     * 飞龙
     * 小金
     * 四金
     * 金金金金
     * </pre>
     * 
     * </blockquote>
     * 
     * <h3>关于 default {@link ToStringConfig}:</h3>
     * <blockquote>
     * 
     * <p>
     * 如果参数 <code>toStringConfig</code> 是null,则使用默认的规则:<br>
     * </p>
     * 
     * <ol>
     * <li>连接符使用{@link ToStringConfig#DEFAULT_CONNECTOR}</li>
     * <li>拼接null或者empty元素</li>
     * <li>如果元素是null,使用{@link StringUtils#EMPTY}替代拼接</li>
     * <li>最后一个元素后面不拼接拼接符</li>
     * </ol>
     * </blockquote>
     * 
     * <h3>关于 {@link ToStringConfig} prefix(since 1.12.9):</h3>
     * <blockquote>
     * 
     * <p>
     * 如果你需要在拼接每个元素的时候,给每个元素加上前缀, 比如 solr 查询, 运营人员配置了一些商品code ,<code>1533312,1533292,1785442</code>, 此时你需要生成
     * <code>code:1533312 OR code:1533292 OR code:1785442</code> 字符串去solr 中查询
     * </p>
     * 
     * <p>
     * 此时你可以这么调用
     * </p>
     * 
     * <pre>
     * 
     * String configItemCodes = "1533312,1533292,1785442";
     * String[] tokenizeToStringArray = StringUtil.tokenizeToStringArray(configItemCodes, ",");
     * List{@code <String>} list = toList(tokenizeToStringArray);
     * ToStringConfig toStringConfig = new ToStringConfig(" OR ", false, "code:");
     * String string = ConvertUtil.toString(list, toStringConfig);
     * </pre>
     * 
     * <b>返回: </b>
     * 
     * <p>
     * code:1533312 OR code:1533292 OR code:1785442
     * </p>
     * 
     * </blockquote>
     * 
     * @param collection
     *            集合,建议元素泛型不要使用自定义的对象(比如UserCommand等),因为这个方法是迭代collection,拿每个元素的字符串格式 进行拼接
     * @param toStringConfig
     *            连接字符串 实体
     * @return 如果 <code>collection</code> 是null或者empty,返回 {@link StringUtils#EMPTY}<br>
     *         如果 <code>toStringConfig</code> 是null,使用默认 {@link ToStringConfig#DEFAULT_CONNECTOR}以及 joinNullOrEmpty 进行连接<br>
     *         都不是null,会循环,拼接toStringConfig.getConnector()
     * @see "org.springframework.util.StringUtils#collectionToDelimitedString(Collection, String, String, String)"
     * @see org.apache.commons.collections4.IteratorUtils#toString(Iterator)
     * @see org.apache.commons.lang3.StringUtils#join(Iterable, String)
     * @since 1.8.4 change param order
     */
    public static String toString(final Collection<?> collection,ToStringConfig toStringConfig){
        return isNullOrEmpty(collection) ? EMPTY : toString(collection.toArray(), toStringConfig);
    }

    /**
     * 将数组 <code>arrays</code> 通过{@link ToStringConfig} 拼接成字符串.
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * ConvertUtil.toString(toArray("a","b"),new ToStringConfig())       =   "a,b"
     * 
     * ToStringConfig toStringConfig=new ToStringConfig(",");
     * toStringConfig.setIsJoinNullOrEmpty(false);
     * ConvertUtil.toString(toArray("a","b",null),new ToStringConfig())  =   "a,b"
     * </pre>
     * 
     * </blockquote>
     * 
     * <h3>如果原始类型数组需要转换:</h3>
     * <blockquote>
     * 
     * <p>
     * 需要先使用下列的方式先转成包装类型数组
     * </p>
     * 
     * <ol>
     * <li>{@link ArrayUtils#toObject(boolean[])}</li>
     * <li>{@link ArrayUtils#toObject(byte[])}</li>
     * <li>{@link ArrayUtils#toObject(char[])}</li>
     * <li>{@link ArrayUtils#toObject(double[])}</li>
     * <li>{@link ArrayUtils#toObject(float[])}</li>
     * <li>{@link ArrayUtils#toObject(int[])}</li>
     * <li>{@link ArrayUtils#toObject(long[])}</li>
     * <li>{@link ArrayUtils#toObject(short[])}</li>
     * </ol>
     * </blockquote>
     * 
     * <h3>关于 default {@link ToStringConfig}:</h3>
     * <blockquote>
     * 
     * <p>
     * 如果参数 <code>toStringConfig</code> 是null,则使用默认的规则:<br>
     * </p>
     * 
     * <ol>
     * <li>连接符使用{@link ToStringConfig#DEFAULT_CONNECTOR}</li>
     * <li>拼接null或者empty元素</li>
     * <li>如果元素是null,使用{@link StringUtils#EMPTY}替代拼接</li>
     * <li>最后一个元素后面不拼接拼接符</li>
     * </ol>
     * </blockquote>
     * 
     * <h3>关于 {@link ToStringConfig} prefix(since 1.12.9):</h3>
     * <blockquote>
     * 
     * <p>
     * 如果你需要在拼接每个元素的时候,给每个元素加上前缀, 比如 solr 查询, 运营人员配置了一些商品code ,<code>1533312,1533292,1785442</code>, 此时你需要生成
     * <code>code:1533312 OR code:1533292 OR code:1785442</code> 字符串去solr 中查询
     * </p>
     * 
     * <p>
     * 此时你可以这么调用
     * </p>
     * 
     * <pre>
     * 
     * String configItemCodes = "1533312,1533292,1785442";
     * String{@code []} tokenizeToStringArray = StringUtil.tokenizeToStringArray(configItemCodes, ",");
     * ToStringConfig toStringConfig = new ToStringConfig(" OR ", false, "code:");
     * String string = ConvertUtil.toString(tokenizeToStringArray, toStringConfig);
     * </pre>
     * 
     * <b>返回: </b>
     * 
     * <p>
     * code:1533312 OR code:1533292 OR code:1785442
     * </p>
     * 
     * </blockquote>
     * 
     * @param arrays
     *            支持包装类型,<b>不直接支持</b>原始类型
     * @param toStringConfig
     *            the to string config
     * @return 如果 <code>arrays</code> 是null 或者Empty,返回 {@link StringUtils#EMPTY}<br>
     *         如果 <code>toStringConfig</code> 是null,使用默认 {@link ToStringConfig#DEFAULT_CONNECTOR}以及 joinNullOrEmpty 进行连接<br>
     *         否则循环,拼接 {@link ToStringConfig#getConnector()}
     * @see org.apache.commons.lang3.builder.ToStringStyle
     * @see org.apache.commons.lang3.StringUtils#join(Object[], String)
     * @see org.apache.commons.lang3.StringUtils#join(Iterable, String)
     * @since 1.8.4 change param order
     */
    public static String toString(Object[] arrays,ToStringConfig toStringConfig){
        if (isNullOrEmpty(arrays)){
            return EMPTY;
        }

        //---------------------------------------------------------------
        ToStringConfig useToStringConfig = defaultIfNull(toStringConfig, new ToStringConfig());
        String connector = useToStringConfig.getConnector();
        boolean isJoinNullOrEmpty = useToStringConfig.getIsJoinNullOrEmpty();
        String prefix = useToStringConfig.getPrefix();

        //---------------------------------------------------------------
        StringBuilder sb = new StringBuilder();
        for (Object element : arrays){
            //如果是null或者empty,但是参数值是不拼接,那么跳过,继续循环
            if (isNullOrEmpty(element) && !isJoinNullOrEmpty){
                continue;
            }
            //---------------------------------------------------------------
            //since 1.12.9 support prefix
            sb.append(defaultIfNull(prefix, EMPTY));

            //value转换
            //注意:如果value是null,StringBuilder 将拼接 "null" 字符串,详见 java.lang.AbstractStringBuilder#append(String)
            sb.append(defaultIfNull(element, EMPTY)); //see StringUtils.defaultString(t)

            //---------------------------------------------------------------
            if (null != connector){//注意可能传过来的是换行符,不能使用Validator.isNullOrEmpty来判断
                sb.append(connector);//放心大胆的拼接 connector, 不判断是否是最后一个,最后会截取
            }
        }
        return StringUtil.substringWithoutLast(sb, connector);
    }

    //---------------------------------------------------------------

    /**
     * 将集合 <code>collection</code> 转成<code>Enumeration</code>.
     * 
     * <h3>说明:</h3>
     * <blockquote>
     * <ol>
     * <li>一般情况,你可能不需要这个方法,不过在一些API的时候,需要<code>Enumeration</code>参数,此时调用这个方法来进行转换会比较方便</li>
     * </ol>
     * </blockquote>
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * ConvertUtil.toEnumeration(null) = Collections.emptyEnumeration()
     * </pre>
     * 
     * </blockquote>
     * 
     * @param <T>
     *            the generic type
     * @param collection
     *            集合
     * @return 如果 <code>collection</code> 是null,返回 {@link Collections#emptyEnumeration()}<br>
     *         否则返回{@link Collections#enumeration(Collection)}
     * @see Collections#enumeration(Collection)
     * @since 1.4.0
     */
    public static <T> Enumeration<T> toEnumeration(final Collection<T> collection){
        return null == collection ? Collections.<T> emptyEnumeration() : Collections.enumeration(collection);
    }

    //---------------------------------------------------------------
    //toMap

    /**
     * 将 <code>key</code> 和 <code>value</code> 直接转成map.
     * 
     * <h3>说明:</h3>
     * <blockquote>
     * <ol>
     * <li>返回是的是 {@link LinkedHashMap}</li>
     * 
     * <li>
     * <p>
     * 非常适合单key的场景,比如
     * </p>
     * 
     * <pre class="code">
     * Map{@code <String, String>} paramMap = newHashMap();
     * paramMap.put("name", "jinxin");
     * request.setParamMap(paramMap);
     * </pre>
     * 
     * 上面的3行代码可以重写成
     * 
     * <pre class="code">
     * request.setParamMap(toMap("name", "jinxin"));
     * </pre>
     * 
     * <p>
     * 一行代码就搞定了,很简洁,有木有~~
     * </p>
     * 
     * </li>
     * </ol>
     * </blockquote>
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * LOGGER.debug(JsonUtil.format(ConvertUtil.toMap("张飞", "丈八蛇矛")));
     * </pre>
     * 
     * <b>返回:</b>
     * 
     * <pre class="code">
     * {"张飞": "丈八蛇矛"}
     * </pre>
     * 
     * </blockquote>
     * 
     * 
     * <h3>重构:</h3>
     * 
     * <blockquote>
     * <p>
     * 对于以下代码:
     * </p>
     * 
     * <pre class="code">
     * private List{@code <ShopCommand>} loadShopCommandList(){
     *     Map{@code <String, Object>} paraMap = newHashMap();
     *     paraMap.put("orgTypeId", OrgType.ID_SHOP_TYPE);
     * 
     *     return shopCommandDao.findShopListByOrgaTypeId(paraMap);
     * }
     * </pre>
     * 
     * <b>可以重构成:</b>
     * 
     * <pre class="code">
     * private List{@code <ShopCommand>} loadShopCommandList(){
     *   Map{@code <String, Object>} paraMap = ConvertUtil.toMap("orgTypeId", <span style="color:red">(Object)</span> OrgType.ID_SHOP_TYPE);
     *     return shopCommandDao.findShopListByOrgaTypeId(paraMap);
     * }
     * </pre>
     * 
     * </blockquote>
     * 
     * @param <K>
     *            the key type
     * @param <V>
     *            the value type
     * @param key
     *            the key
     * @param value
     *            the value
     * @return 将 <code>key</code> 和 <code>value</code> 直接转成map
     * @see org.apache.commons.lang3.ArrayUtils#toMap(Object[])
     * @see java.util.Collections#singletonMap(Object, Object)
     * @see "com.google.common.collect.ImmutableMap#of(K, V)"
     * @since 1.7.1
     */
    public static <K, V> Map<K, V> toMap(K key,V value){
        Map<K, V> map = new LinkedHashMap<>();//不设置初始值 ,可能调用再PUT 这样浪费性能
        map.put(key, value);
        return map;
    }

    /**
     * 将 <code>key1</code> 和 <code>value1</code>/<code>key2</code> 和 <code>value2</code> 直接转成map.
     * 
     * <h3>说明:</h3>
     * <blockquote>
     * <ol>
     * <li>返回是的是 {@link LinkedHashMap}</li>
     * 
     * <li>
     * <p>
     * 非常适合2个key的场景,比如
     * </p>
     * 
     * <pre class="code">
     * Map{@code <String, String>} paramMap =newHashMap();
     * paramMap.put("name", "jinxin");
     * paramMap.put("age", "18");
     * request.setParamMap(paramMap);
     * </pre>
     * 
     * 上面的3行代码可以重写成
     * 
     * <pre class="code">
     * request.setParamMap(toMap("name", "jinxin", "age", "18"));
     * </pre>
     * 
     * <p>
     * 一行代码就搞定了,很简洁,有木有~~
     * </p>
     * 
     * </li>
     * </ol>
     * </blockquote>
     * 
     * <h3>重构:</h3>
     * 
     * <blockquote>
     * <p>
     * 对于以下代码:
     * </p>
     * 
     * <pre class="code">
     * Map{@code <String, Long>} map = newHashMap();
     * map.put("itemId", itemId);
     * map.put("memberId", memberId);
     * memberFavoritesDao.findMemberFavoritesByMemberIdAndItemId(map);
     * </pre>
     * 
     * <b>可以重构成:</b>
     * 
     * <pre class="code">
     * Map{@code <String, Long>} map = ConvertUtil.toMap("itemId", itemId, "memberId", memberId);
     * memberFavoritesDao.findMemberFavoritesByMemberIdAndItemId(map);
     * </pre>
     * 
     * </blockquote>
     *
     * @param <K>
     *            the key type
     * @param <V>
     *            the value type
     * @param key1
     *            the key 1
     * @param value1
     *            the value 1
     * @param key2
     *            the key 2
     * @param value2
     *            the value 2
     * @return 将 <code>key1</code> 和 <code>value1</code>/<code>key2</code> 和 <code>value2</code> 直接转成map
     * @see org.apache.commons.lang3.ArrayUtils#toMap(Object[])
     * @see java.util.Collections#singletonMap(Object, Object)
     * @see "com.google.common.collect.ImmutableMap#of(K, V)"
     * @since 1.9.5
     */
    public static <K, V> Map<K, V> toMap(K key1,V value1,K key2,V value2){
        Map<K, V> map = toMap(key1, value1);
        map.put(key2, value2);
        return map;
    }

    /**
     * 将 <code>properties</code> 转换成map.
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * Properties properties = new Properties();
     * 
     * properties.setProperty("name", "feilong");
     * properties.setProperty("age", "18");
     * properties.setProperty("country", "china");
     * 
     * LOGGER.debug(JsonUtil.format(toMap(properties)));
     * </pre>
     * 
     * <b>返回:</b>
     * 
     * <pre class="code">
     * {
     * "age": "18",
     * "country": "china",
     * "name": "feilong"
     * }
     * </pre>
     * 
     * </blockquote>
     * 
     * <h3>说明:</h3>
     * <blockquote>
     * <ol>
     * <li>返回的map 经过了 {@link SortUtil#sortMapByKeyAsc(Map)}排序处理,方便输出日志</li>
     * </ol>
     * </blockquote>
     * 
     * <h3>关于 <code>Properties</code></h3>
     * 
     * <blockquote>
     * <p>
     * Properties 是 Map的实现类 ,其 key和value 是String 类型.
     * </p>
     * 
     * <p>
     * 因此Properties 可以强制转换成map
     * </p>
     * </blockquote>
     * 
     * @param properties
     *            the properties
     * @return 如果 <code>properties</code> 是null或者empty,返回 {@link Collections#emptyMap()}<br>
     * @see org.apache.commons.collections4.MapUtils#toProperties(Map)
     * @since 1.7.1
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static Map<String, String> toMap(Properties properties){
        if (isNullOrEmpty(properties)){
            return emptyMap();
        }
        return sortMapByKeyAsc((Map) properties);//为了log方便,使用 treeMap
    }

    /**
     * 将诸如 Map{@code <String, String>} 类型转成 Map{@code <String, Integer>} 类型.
     * 
     * <h3>说明:</h3>
     * <blockquote>
     * <ol>
     * <li>适合只是简单的将key value类型转换,而不需要自己再构建Transformer,再去调用 {@link #toMap(Map, Transformer, Transformer)} ,简化操作</li>
     * <li>返回的是 {@link LinkedHashMap},顺序依照入参 inputMap</li>
     * <li>返回的是新的map,原来的<code>toMap</code>参数不受影响</li>
     * <li>也支持诸如 Map{@code <String, Integer>} 转 Map{@code <String, String>} (key和value 使用不同的转换器)</li>
     * <li>也支持诸如 Map{@code <String, String>} 转 Map{@code <String, Integer[]>} (单值转数组)</li>
     * <li>也支持诸如 Map{@code <String[], String[]>} 转 Map{@code <String[], Long[]>} (数组转数组)</li>
     * </ol>
     * </blockquote>
     * 
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <p>
     * <b>场景1:</b> 将Map{@code <String, String>} 转 Map{@code <String, Integer>} 类型
     * </p>
     * 
     * <pre class="code">
     * 
     * Map{@code <String, String>} map = toMap("1", "2");
     * Map{@code <String, Integer>} returnMap = toMap(map, Integer.class);
     * 
     * <span style="color:green">// 输出测试</span>
     * for (Map.Entry{@code <String, Integer>} entry : returnMap.entrySet()){
     *     String key = entry.getKey();
     *     Integer value = entry.getValue();
     *     LOGGER.debug("key:[{}],value:[{}]", key, value);
     * }
     * 
     * </pre>
     * 
     * <b>返回:</b>
     * 
     * <pre class="code">
     * key:["1"],value:[2]
     * </pre>
     * 
     * <hr>
     * 
     * <p>
     * <b>场景2:</b> Map{@code <String, String>} 转 Map{@code <String, Integer[]>}
     * </p>
     * 
     * <pre class="code">
     * 
     * Map{@code <String, String>} map = toMap("1", "2,2");
     * 
     * <span style="color:green">//key和value转成不同的类型</span>
     * Map{@code <String, Integer[]>} returnMap = toMap(map,  Integer[].class);
     * 
     * <span style="color:green">// 输出测试</span>
     * for (Map.Entry{@code <String, Integer[]>} entry : returnMap.entrySet()){
     *     String key = entry.getKey();
     *     Integer[] value = entry.getValue();
     * 
     *     LOGGER.debug("key:[{}],value:[{}]", key, value);
     * }
     * 
     * </pre>
     * 
     * <b>返回:</b>
     * 
     * <pre class="code">
     * key:["1"],value:[[2, 2]]
     * </pre>
     * 
     * <hr>
     * 
     * <p>
     * <b>场景3:</b> Map{@code <String[], String[]>} 转 Map{@code <String[], Long[]>}
     * </p>
     * 
     * <pre class="code">
     * 
     * Map{@code <String[], String[]>} map = toMap(toArray("1"), toArray("2", "8"));
     * 
     * <span style="color:green">//key和value转成不同的类型</span>
     * Map{@code <String[], Long[]>} returnMap = toMap(map, Long[].class);
     * 
     * assertThat(returnMap, allOf(hasEntry(toArray("1"), toArray(2L, 8L))));
     * </pre>
     * 
     * </blockquote>
     *
     * @param <K>
     *            the key type
     * @param <V>
     *            the value type
     * @param <J>
     *            返回的map ,value的类型
     * @param inputMap
     *            the input map
     * @param valueTargetType
     *            value 需要转换成什么类型,类型可以和原map的类型相同或者可以设置为null,均表示返回的map使用<code>inputMap</code>原样的<code>value</code>,不会进行类型转换
     * @return 如果 <code>inputMap</code> 是null或者empty,返回 {@link Collections#emptyMap()}<br>
     *         如果 <code>valueTargetType</code> 是null,那么value 直接使用<code>inputMap</code>的 value<br>
     * @see #toMap(Map, Class, Class)
     * @see <a href="https://github.com/venusdrogon/feilong-core/issues/661">issues661</a>
     * @since 1.10.5
     */
    public static <K, V, J> Map<K, J> toMap(Map<K, V> inputMap,final Class<J> valueTargetType){
        return toMap(inputMap, null, valueTargetType);
    }

    /**
     * 将诸如 Map{@code <String, String>} 类型转成 Map{@code <Integer, Integer>} 类型.
     * 
     * <h3>说明:</h3>
     * <blockquote>
     * <ol>
     * <li>适合只是简单的将key value类型转换,而不需要自己再构建Transformer,再去调用 {@link #toMap(Map, Transformer, Transformer)} ,简化操作</li>
     * <li>返回的是 {@link LinkedHashMap},顺序依照入参 inputMap</li>
     * <li>返回的是新的map,原来的<code>toMap</code>参数不受影响</li>
     * <li>也支持诸如 Map{@code <String, Integer>} 转 Map{@code <Integer, String>} (key和value 使用不同的转换器)</li>
     * <li>也支持诸如 Map{@code <String, String>} 转 Map{@code <Integer, Integer[]>} (单值转数组)</li>
     * <li>也支持诸如 Map{@code <String[], String[]>} 转 Map{@code <Integer[], Long[]>} (数组转数组)</li>
     * </ol>
     * </blockquote>
     * 
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <p>
     * <b>场景1:</b> 将Map{@code <String, String>} 转 Map{@code <Integer, Integer>} 类型
     * </p>
     * 
     * <pre class="code">
     * 
     * Map{@code <String, String>} map = toMap("1", "2");
     * Map{@code <Integer, Integer>} returnMap = toMap(map, Integer.class, Integer.class);
     * 
     * <span style="color:green">// 输出测试</span>
     * for (Map.Entry{@code <Integer, Integer>} entry : returnMap.entrySet()){
     *     Integer key = entry.getKey();
     *     Integer value = entry.getValue();
     *     LOGGER.debug("key:[{}],value:[{}]", key, value);
     * }
     * 
     * </pre>
     * 
     * <b>返回:</b>
     * 
     * <pre class="code">
     * key:[1],value:[2]
     * </pre>
     * 
     * <hr>
     * 
     * <p>
     * <b>场景2:</b> Map{@code <String, String>} 转 Map{@code <Integer, Integer[]>}
     * </p>
     * 
     * <pre class="code">
     * 
     * Map{@code <String, String>} map = toMap("1", "2,2");
     * 
     * <span style="color:green">//key和value转成不同的类型</span>
     * Map{@code <Integer, Integer[]>} returnMap = toMap(map, Integer.class, Integer[].class);
     * 
     * <span style="color:green">// 输出测试</span>
     * for (Map.Entry{@code <Integer, Integer[]>} entry : returnMap.entrySet()){
     *     Integer key = entry.getKey();
     *     Integer[] value = entry.getValue();
     * 
     *     LOGGER.debug("key:[{}],value:[{}]", key, value);
     * }
     * 
     * </pre>
     * 
     * <b>返回:</b>
     * 
     * <pre class="code">
     * key:[1],value:[[2, 2]]
     * </pre>
     * 
     * <hr>
     * 
     * <p>
     * <b>场景3:</b> Map{@code <String[], String[]>} 转 Map{@code <Integer[], Long[]>}
     * </p>
     * 
     * <pre class="code">
     * 
     * Map{@code <String[], String[]>} map = toMap(toArray("1"), toArray("2", "8"));
     * 
     * <span style="color:green">//key和value转成不同的类型</span>
     * Map{@code <Integer[], Long[]>} returnMap = toMap(map, Integer[].class, Long[].class);
     * 
     * assertThat(returnMap, allOf(hasEntry(toArray(1), toArray(2L, 8L))));
     * </pre>
     * 
     * </blockquote>
     * 
     * @param <K>
     *            the key type
     * @param <V>
     *            the value type
     * @param <I>
     *            返回的map ,key的类型
     * @param <J>
     *            返回的map ,value的类型
     * @param inputMap
     *            the input map
     * @param keyTargetType
     *            key需要转换成什么类型,类型可以和原map的类型相同或者可以设置为null,均表示返回的map使用<code>inputMap</code>原样的<code>key</code>,不会进行类型转换
     * @param valueTargetType
     *            value 需要转换成什么类型,类型可以和原map的类型相同或者可以设置为null,均表示返回的map使用<code>inputMap</code>原样的<code>value</code>,不会进行类型转换
     * @return 如果 <code>inputMap</code> 是null或者empty,返回 {@link Collections#emptyMap()}<br>
     *         如果 <code>keyTargetType</code> 是null,那么key直接使用<code>inputMap</code>的key<br>
     *         如果 <code>valueTargetType</code> 是null,那么value 直接使用<code>inputMap</code>的 value<br>
     * @see #toMap(Map, Transformer, Transformer)
     * @see <a href="https://github.com/venusdrogon/feilong-core/issues/497">issues497</a>
     * @since 1.9.2
     */
    public static <K, V, I, J> Map<I, J> toMap(Map<K, V> inputMap,final Class<I> keyTargetType,final Class<J> valueTargetType){
        if (isNullOrEmpty(inputMap)){
            return emptyMap();
        }

        Transformer<K, I> keyTransformer = null == keyTargetType ? null : new SimpleClassTransformer<K, I>(keyTargetType);
        Transformer<V, J> valueTransformer = null == valueTargetType ? null : new SimpleClassTransformer<V, J>(valueTargetType);

        return toMap(inputMap, keyTransformer, valueTransformer);
    }

    /**
     * 将诸如 Map{@code <String, String>} 类型转成 Map{@code <Integer, Integer>} 类型.
     * 
     * <h3>说明:</h3>
     * <blockquote>
     * <ol>
     * <li>适合复杂的类型转换场景,如果只是简单的类型转换,你可以直接调用 {@link #toMap(Map, Class, Class)}</li>
     * <li>返回的是 {@link LinkedHashMap},顺序依照入参 inputMap</li>
     * <li>返回的是新的map,原来的<code>toMap</code>参数不受影响</li>
     * <li>也支持诸如 Map{@code <String, Integer>} 转 Map{@code <Integer, String>} (key和value 使用不同的转换器)</li>
     * <li>也支持诸如 Map{@code <String, String>} 转 Map{@code <Integer, Integer[]>} (单值转数组)</li>
     * <li>也支持诸如 Map{@code <String[], String[]>} 转 Map{@code <Integer[], Long[]>} (数组转数组)</li>
     * </ol>
     * </blockquote>
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <p>
     * <b>场景1:</b> 将Map{@code <String, String>} 转 Map{@code <Integer, Integer>} 类型
     * </p>
     * 
     * <pre class="code">
     * 
     * Map{@code <String, String>} map = toMap("1", "2");
     * 
     * <span style="color:green">//key和value 都转成integer 使用相同的转换器</span>
     * Transformer{@code <String, Integer>} transformer = new SimpleClassTransformer{@code <>}(Integer.class);
     * 
     * Map{@code <Integer, Integer>} returnMap = toMap(map, transformer, transformer);
     * 
     * <span style="color:green">// 输出测试</span>
     * for (Map.Entry{@code <Integer, Integer>} entry : returnMap.entrySet()){
     *     Integer key = entry.getKey();
     *     Integer value = entry.getValue();
     *     LOGGER.debug("key:[{}],value:[{}]", key, value);
     * }
     * 
     * </pre>
     * 
     * <b>返回:</b>
     * 
     * <pre class="code">
     * key:[1],value:[2]
     * </pre>
     * 
     * <hr>
     * 
     * <p>
     * <b>场景2:</b> Map{@code <String, String>} 转 Map{@code <Integer, Integer[]>}
     * </p>
     * 
     * <pre class="code">
     * 
     * Map{@code <String, String>} map = toMap("1", "2,2");
     * 
     * Transformer{@code <String, Integer>} keyTransformer = new SimpleClassTransformer{@code <>}(Integer.class);
     * Transformer{@code <String, Integer[]>} valueTransformer = new SimpleClassTransformer{@code <>}(Integer[].class);
     * 
     * <span style="color:green">//key和value转成不同的类型</span>
     * Map{@code <Integer, Integer[]>} returnMap = toMap(map, keyTransformer, valueTransformer);
     * 
     * <span style="color:green">// 输出测试</span>
     * for (Map.Entry{@code <Integer, Integer[]>} entry : returnMap.entrySet()){
     *     Integer key = entry.getKey();
     *     Integer[] value = entry.getValue();
     * 
     *     LOGGER.debug("key:[{}],value:[{}]", key, value);
     * }
     * 
     * </pre>
     * 
     * <b>返回:</b>
     * 
     * <pre class="code">
     * key:[1],value:[[2, 2]]
     * </pre>
     * 
     * <hr>
     * 
     * <p>
     * <b>场景3:</b> Map{@code <String[], String[]>} 转 Map{@code <Integer[], Long[]>}
     * </p>
     * 
     * <pre class="code">
     * 
     * Map{@code <String[], String[]>} map = toMap(toArray("1"), toArray("2", "8"));
     * 
     * Transformer{@code <String[], Integer[]>} keyTransformer = new SimpleClassTransformer{@code <>}(Integer[].class);
     * Transformer{@code <String[], Long[]>} valueTransformer = new SimpleClassTransformer{@code <>}(Long[].class);
     * 
     * <span style="color:green">//key和value转成不同的类型</span>
     * Map{@code <Integer[], Long[]>} returnMap = toMap(map, keyTransformer, valueTransformer);
     * 
     * assertThat(returnMap, allOf(hasEntry(toArray(1), toArray(2L, 8L))));
     * </pre>
     * 
     * </blockquote>
     *
     * @param <K>
     *            the key type
     * @param <V>
     *            the value type
     * @param <I>
     *            返回的map ,key的类型
     * @param <J>
     *            返回的map ,value的类型
     * @param inputMap
     *            the input map
     * @param keyTransformer
     *            key 转换器,如果是null,那么key直接使用<code>inputMap</code>的key<br>
     * @param valueTransformer
     *            value 转换器,如果是null,那么value直接使用<code>inputMap</code>的value<br>
     * @return 如果 <code>inputMap</code> 是null或者empty,返回 {@link Collections#emptyMap()}<br>
     *         如果 <code>keyTransformer</code> 是null,那么key直接使用<code>inputMap</code>的key<br>
     *         如果 <code>valueTransformer</code> 是null,那么value 直接使用<code>inputMap</code>的 value<br>
     * @see org.apache.commons.collections4.MapUtils#transformedMap(Map, Transformer, Transformer)
     * @see org.apache.commons.collections4.map.TransformedMap#transformedMap(Map, Transformer, Transformer)
     * @see <a href="https://github.com/venusdrogon/feilong-core/issues/497">issues497</a>
     * @since 1.9.2
     */
    @SuppressWarnings("unchecked")
    public static <K, V, I, J> Map<I, J> toMap(
                    Map<K, V> inputMap,
                    final Transformer<K, I> keyTransformer,
                    final Transformer<V, J> valueTransformer){
        if (isNullOrEmpty(inputMap)){
            return emptyMap();
        }

        //---------------------------------------------------------------

        Map<I, J> returnMap = new LinkedHashMap<>(inputMap.size());

        for (Map.Entry<K, V> entry : inputMap.entrySet()){
            K key = entry.getKey();
            V value = entry.getValue();

            returnMap.put(
                            null == keyTransformer ? (I) key : keyTransformer.transform(key),
                            null == valueTransformer ? (J) value : valueTransformer.transform(value));
        }
        return returnMap;
    }

    /**
     * 将 <code>mapEntryCollection</code> 转成map ({@link LinkedHashMap}).
     * 
     * <h3>说明:</h3>
     * 
     * <blockquote>
     * <ol>
     * <li>返回是的是 {@link LinkedHashMap},顺序依照参数 <code>mapEntryCollection</code>,key是 {@link java.util.Map.Entry#getKey()},value 是
     * {@link java.util.Map.Entry#getValue()}</li>
     * <li>{@link java.util.Map.Entry} 已知实现类,你可以使用 {@link Pair},或者 {@link java.util.AbstractMap.SimpleEntry}</li>
     * </ol>
     * </blockquote>
     * 
     * <h3>{@link Pair} 示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * Map{@code <String, String>} map = toMap(toList(//
     *                 Pair.of("张飞", "丈八蛇矛"),
     *                 Pair.of("关羽", "青龙偃月刀"),
     *                 Pair.of("赵云", "龙胆枪"),
     *                 Pair.of("刘备", "双股剑")));
     * LOGGER.debug(JsonUtil.format(map));
     * </pre>
     * 
     * <b>返回:</b>
     * 
     * <pre class="code">
     * {
     * "张飞": "丈八蛇矛",
     * "关羽": "青龙偃月刀",
     * "赵云": "龙胆枪",
     * "刘备": "双股剑"
     * }
     * </pre>
     * 
     * </blockquote>
     * 
     * <h3>{@link java.util.AbstractMap.SimpleEntry} 示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * Map{@code <String, String>} map = ConvertUtil.toMap(
     *                 toList(
     *                                 new SimpleEntry{@code <>}("张飞", "丈八蛇矛"),
     *                                 new SimpleEntry{@code <>}("关羽", "青龙偃月刀"),
     *                                 new SimpleEntry{@code <>}("赵云", "龙胆枪"),
     *                                 new SimpleEntry{@code <>}("刘备", "双股剑")));
     * LOGGER.debug(JsonUtil.format(map));
     * </pre>
     * 
     * <b>返回:</b>
     * 
     * <pre class="code">
     * {
     * "张飞": "丈八蛇矛",
     * "关羽": "青龙偃月刀",
     * "赵云": "龙胆枪",
     * "刘备": "双股剑"
     * }
     * </pre>
     * 
     * </blockquote>
     *
     * @param <V>
     *            the value type
     * @param <K>
     *            the key type
     * @param <E>
     *            the element type
     * @param mapEntryCollection
     *            the map entry collection
     * @return 如果 <code>mapEntryCollection</code> 是null,返回 {@link Collections#emptyMap()}<br>
     *         如果 <code>mapEntryCollection</code> 有元素是null,将会抛出异常 {@link IllegalArgumentException}
     * @see org.apache.commons.lang3.ArrayUtils#toMap(Object[])
     * @since 1.7.1
     */
    public static <V, K, E extends Map.Entry<K, V>> Map<K, V> toMap(Collection<E> mapEntryCollection){
        if (null == mapEntryCollection){
            return emptyMap();
        }

        Validate.noNullElements(mapEntryCollection, "mapEntryCollection can't has null elememt!");

        Map<K, V> map = newLinkedHashMap(mapEntryCollection.size());
        for (Map.Entry<K, V> entry : mapEntryCollection){
            map.put(entry.getKey(), entry.getValue());
        }
        return map;
    }

    /**
     * 将 {@link java.util.Map.Entry}数组转成map ({@link LinkedHashMap}).
     * 
     * <h3>说明:</h3>
     * 
     * <blockquote>
     * <ol>
     * <li>返回是的是 {@link LinkedHashMap},顺序依照参数 {@link java.util.Map.Entry}数组顺序,key是 {@link java.util.Map.Entry#getKey()},value 是
     * {@link java.util.Map.Entry#getValue()}</li>
     * <li>{@link java.util.Map.Entry} 已知实现类,你可以使用 {@link Pair},或者 {@link java.util.AbstractMap.SimpleEntry}</li>
     * </ol>
     * </blockquote>
     * 
     * <h3>{@link Pair} 示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * Map{@code <String, String>} map = ConvertUtil.toMapUseEntrys(
     *                 Pair.of("张飞", "丈八蛇矛"),
     *                 Pair.of("关羽", "青龙偃月刀"),
     *                 Pair.of("赵云", "龙胆枪"),
     *                 Pair.of("刘备", "双股剑"));
     * LOGGER.debug(JsonUtil.format(map));
     * </pre>
     * 
     * <b>返回:</b>
     * 
     * <pre class="code">
     * {
     * "张飞": "丈八蛇矛",
     * "关羽": "青龙偃月刀",
     * "赵云": "龙胆枪",
     * "刘备": "双股剑"
     * }
     * 
     * </pre>
     * 
     * </blockquote>
     * 
     * <h3>{@link java.util.AbstractMap.SimpleEntry} 示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * 
     * Map{@code <String, String>} map = ConvertUtil.toMapUseEntrys(
     *                 new SimpleEntry{@code <>}("张飞", "丈八蛇矛"),
     *                 new SimpleEntry{@code <>}("关羽", "青龙偃月刀"),
     *                 new SimpleEntry{@code <>}("赵云", "龙胆枪"),
     *                 new SimpleEntry{@code <>}("刘备", "双股剑"));
     * LOGGER.debug(JsonUtil.format(map));
     * 
     * </pre>
     * 
     * <b>返回:</b>
     * 
     * <pre class="code">
     * {
     * "张飞": "丈八蛇矛",
     * "关羽": "青龙偃月刀",
     * "赵云": "龙胆枪",
     * "刘备": "双股剑"
     * }
     * 
     * </pre>
     * 
     * </blockquote>
     * 
     * 
     * <h3>重构:</h3>
     * 
     * <blockquote>
     * <p>
     * 以前初始化全局map的时候,你可能会这么写
     * </p>
     * 
     * <pre class="code">
     * 
     * <span style="color:green">// 除数和单位的map,必须是有顺序的 从大到小.</span>
     * private static final Map{@code <Long, String>} DIVISOR_AND_UNIT_MAP = new LinkedHashMap{@code <>}();
     * 
     * static{
     *     DIVISOR_AND_UNIT_MAP.put(FileUtils.ONE_TB, "TB");<span style=
    "color:green">//(Terabyte,太字节,或百万兆字节)=1024GB,其中1024=2^10(2的10次方)</span>
     *     DIVISOR_AND_UNIT_MAP.put(FileUtils.ONE_GB, "GB");<span style="color:green">//(Gigabyte,吉字节,又称“千兆”)=1024MB</span>
     *     DIVISOR_AND_UNIT_MAP.put(FileUtils.ONE_MB, "MB");<span style="color:green">//(Megabyte,兆字节,简称“兆”)=1024KB</span>
     *     DIVISOR_AND_UNIT_MAP.put(FileUtils.ONE_KB, "KB");<span style="color:green">//(Kilobyte 千字节)=1024B</span>
     * }
     * 
     * </pre>
     * 
     * <b>现在你可以重构成:</b>
     * 
     * <pre class="code">
     * 
     * <span style="color:green">// 除数和单位的map,必须是有顺序的 从大到小.</span>
     * private static final Map{@code <Long, String>} DIVISOR_AND_UNIT_MAP = ConvertUtil.toMapUseEntrys(
     *                 Pair.of(FileUtils.ONE_TB, "TB"), <span style="color:green">//(Terabyte,太字节,或百万兆字节)=1024GB,其中1024=2^10(2的10次方) </span>
     *                 Pair.of(FileUtils.ONE_GB, "GB"), <span style="color:green">//(Gigabyte,吉字节,又称“千兆”)=1024MB</span>
     *                 Pair.of(FileUtils.ONE_MB, "MB"), <span style="color:green">//(Megabyte,兆字节,简称“兆”)=1024KB</span>
     *                 Pair.of(FileUtils.ONE_KB, "KB")); <span style="color:green">//(Kilobyte 千字节)=1024B</span>
     * 
     * </pre>
     * 
     * <p>
     * 代码更加简洁
     * </p>
     * 
     * </blockquote>
     *
     * @param <V>
     *            the value type
     * @param <K>
     *            the key type
     * @param mapEntrys
     *            the entrys
     * @return 如果 <code>entrys</code> 是null,返回 {@link Collections#emptyMap()}<br>
     *         如果 <code>entrys</code> 有元素是null,将会抛出异常 {@link IllegalArgumentException}
     * @see org.apache.commons.lang3.tuple.ImmutablePair#ImmutablePair(Object, Object)
     * @see org.apache.commons.lang3.tuple.Pair#of(Object, Object)
     * @since 1.7.1
     * @since 1.9.5 change name
     */
    @SafeVarargs
    public static <V, K> Map<K, V> toMapUseEntrys(Map.Entry<K, V>...mapEntrys){
        if (null == mapEntrys){
            return emptyMap();
        }
        Validate.noNullElements(mapEntrys, "mapEntrys can't has null elememt!");

        Map<K, V> map = newLinkedHashMap(mapEntrys.length);
        for (Map.Entry<K, V> entry : mapEntrys){
            map.put(entry.getKey(), entry.getValue());
        }
        return map;
    }

    //-------------------------toProperties--------------------------------------

    /**
     * 将map转成 {@link Properties}.
     * 
     * <h3>说明:</h3>
     * <blockquote>
     * <ol>
     * <li>由于 Properties 只能保存非空的key和value,因此如果map 有key或者value是null,将会抛出{@link NullPointerException}</li>
     * </ol>
     * </blockquote>
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * Map{@code <String, String>} map = toMap("name", "feilong");
     * Properties properties = ConvertUtil.toProperties(map);
     * 
     * LOGGER.debug(JsonUtil.format(properties));
     * </pre>
     * 
     * <b>返回:</b>
     * 
     * <pre class="code">
     * {"name": "feilong"}
     * </pre>
     * 
     * </blockquote>
     * 
     * @param map
     *            the map
     * @return 如果 <code>map</code> 是null,返回 empty Properties<br>
     * @see org.apache.commons.collections4.MapUtils#toProperties(Map)
     * @since 1.7.3
     */
    public static Properties toProperties(final Map<String, String> map){
        return MapUtils.toProperties(map);
    }

    //--------------------------toList-------------------------------------

    /**
     * 将枚举 <code>enumeration</code> 转成 {@link List}.
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * toList((Enumeration{@code <String>}) null) = emptyList()
     * </pre>
     * 
     * </blockquote>
     * 
     * @param <T>
     *            the generic type
     * @param enumeration
     *            the enumeration
     * @return 如果 <code>enumeration</code> 是null,返回 {@link Collections#emptyList()}<br>
     *         否则返回 {@link Collections#list(Enumeration)}
     * @see Collections#emptyList()
     * @see Collections#EMPTY_LIST
     * @see Collections#list(Enumeration)
     * @see EnumerationUtils#toList(Enumeration)
     * @since 1.0.7
     */
    public static <T> List<T> toList(final Enumeration<T> enumeration){
        return null == enumeration ? Collections.<T> emptyList() : Collections.list(enumeration);
    }

    /**
     * 将 集合 <code>collection</code> 转成 list.
     * 
     * <h3>说明:</h3>
     * <blockquote>
     * <ol>
     * <li>此方法很适合快速的将set转成list这样的操作</li>
     * </ol>
     * </blockquote>
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * Set{@code <String>} set = new LinkedHashSet{@code <>}();
     * Collections.addAll(set, "a", "a", "b", "b");
     * LOGGER.debug("{}", toList(set));
     * </pre>
     * 
     * <b>返回:</b>
     * 
     * <pre class="code">
     * [a,b]
     * </pre>
     * 
     * </blockquote>
     *
     * @param <T>
     *            the generic type
     * @param collection
     *            the collection
     * @return 如果 <code>collection</code> 是null,返回 {@link Collections#emptyList()}<br>
     *         如果 <code>collection instanceof List</code>,那么强转成 list返回<br>
     *         否则返回 <code>new ArrayList(collection)</code>
     * @see org.apache.commons.collections4.IterableUtils#toList(Iterable)
     * @see org.apache.commons.collections4.IteratorUtils#toList(Iterator)
     * @since 1.6.1
     */
    public static <T> List<T> toList(final Collection<T> collection){
        if (null == collection){
            return Collections.<T> emptyList();
        }
        return collection instanceof List ? (List<T>) collection : new ArrayList<T>(collection);
    }

    /**
     * 数组转成 ({@link java.util.ArrayList ArrayList}).
     * 
     * <h3>说明:</h3>
     * <blockquote>
     * <ol>
     * <li>此方法返回的list可以进行add等操作</li>
     * <li>如果直接使用{@link java.util.Arrays#asList(Object...) Arrays#asList(Object...)}返回的list没有实现 {@link java.util.Collection#add(Object)
     * Collection#add(Object)}等方法,执行<code>list.add("c")</code>;操作的话会导致异常!</li>
     * <li>而本方法使用 {@link ArrayList#ArrayList(java.util.Collection)} 来进行重新封装返回,可以执行正常的list操作</li>
     * </ol>
     * </blockquote>
     * 
     * 
     * <h3>特别适合:</h3>
     * 
     * <blockquote>
     * 
     * <p>
     * 如果你要通过以下方式来构造list:
     * </p>
     * 
     * <pre class="code">
     * 
     * List{@code <String>} list = new ArrayList{@code <>}();
     * list.add("feilong1");
     * list.add("feilong2");
     * list.add("feilong2");
     * list.add("feilong3");
     * 
     * </pre>
     * 
     * 此时你可以使用:
     * 
     * <pre class="code">
     * List{@code <String>} list = toList("feilong1", "feilong2", "feilong2", "feilong3");
     * </pre>
     * 
     * <p>
     * 代码会更简洁
     * </p>
     * </blockquote>
     * 
     * <h3>甚至于:</h3>
     * 
     * <blockquote>
     * 
     * <p>
     * 有很多时候,参数需要一个对象list,构造的时候,你需要这样
     * </p>
     * 
     * <pre class="code">
     * 
     * List{@code <UserAddress>} userAddresseList = new ArrayList{@code <>}();
     * UserAddress userAddress = new UserAddress();
     * userAddress.setAddress("上海");
     * userAddresseList.add(userAddress);
     * 
     * </pre>
     * 
     * 你可以重构成:
     * 
     * <pre class="code">
     * UserAddress userAddress = new UserAddress();
     * userAddress.setAddress("上海");
     * List{@code <UserAddress>} userAddresseList = toList(userAddress);
     * </pre>
     * 
     * </blockquote>
     * 
     * @param <T>
     *            the generic type
     * @param arrays
     *            T数组
     * @return 如果 <code>arrays</code> 是null或者empty,返回 {@link Collections#emptyList()}<br>
     * 
     *         <span style="color:red">提别提醒:注意动态数组(Varargs)的陷阱:</span>
     * 
     *         <pre class="code">
     *         assertEquals(emptyList(), <span style="color:red">toList((User[]) null)</span>);
     *         
     *         <span style="color:green">//-------------------------------------------------</span>
     * 
     *         List{@code <User>} list = newArrayList();
     *         list.add(null);
     * 
     *         assertEquals(list, <span style="color:red">toList((User) null)</span>);
     *         </pre>
     * 
     *         否则返回 {@code new ArrayList<T>(Arrays.asList(arrays));}
     * @see java.util.Arrays#asList(Object...)
     * @see java.util.Collections#singleton(Object)
     * @see java.util.Collections#addAll(Collection, Object...)
     * @see java.util.Collections#singletonList(Object)
     * @see "org.springframework.util.CollectionUtils#arrayToList(Object)"
     */
    @SafeVarargs
    public static <T> List<T> toList(T...arrays){
        return isNullOrEmpty(arrays) ? Collections.<T> emptyList() : new ArrayList<>(Arrays.asList(arrays));
    }

    //---------------------------toSet------------------------------------

    /**
     * 数组转成 Set ({@link java.util.LinkedHashSet LinkedHashSet}).
     * 
     * <h3>说明:</h3>
     * <blockquote>
     * <ol>
     * <li>此方法返回的是{@link java.util.LinkedHashSet LinkedHashSet}</li>
     * </ol>
     * </blockquote>
     * 
     * <h3>特别适合:</h3>
     * 
     * <blockquote>
     * 
     * <p>
     * 如果你要通过以下方式来构造Set:
     * </p>
     * 
     * <pre class="code">
     * 
     * Set{@code <String>} set = new LinkedHashSet{@code <>}();
     * set.add("feilong1");
     * set.add("feilong2");
     * set.add("feilong2");
     * set.add("feilong3");
     * 
     * </pre>
     * 
     * 此时你可以使用:
     * 
     * <pre class="code">
     * Set{@code <String>} set = toSet("feilong1", "feilong2", "feilong2", "feilong3");
     * </pre>
     * 
     * <p>
     * 代码会更简洁
     * </p>
     * </blockquote>
     * 
     * <h3>甚至于:</h3>
     * 
     * <blockquote>
     * 
     * <p>
     * 有很多时候,参数需要一个对象Set,构造的时候,你需要这样
     * </p>
     * 
     * <pre class="code">
     * Set{@code <UserAddress>} userAddresseSet = new LinkedHashSet{@code <>}();
     * UserAddress userAddress = new UserAddress();
     * userAddress.setAddress("上海");
     * userAddresseSet.add(userAddress);
     * </pre>
     * 
     * 你可以重构成:
     * 
     * <pre class="code">
     * UserAddress userAddress = new UserAddress();
     * userAddress.setAddress("上海");
     * Set{@code <UserAddress>} userAddresseSet = toSet(userAddress);
     * </pre>
     * 
     * </blockquote>
     *
     * @param <T>
     *            the generic type
     * @param arrays
     *            the arrays
     * @return 如果 <code>arrays</code> 是null或者empty,返回 {@link Collections#emptySet()}<br>
     * 
     *         <span style="color:red">提别提醒:注意动态数组(Varargs)的陷阱:</span>
     * 
     *         <pre class="code">
     *         assertEquals(emptySet(), toSet(<span style="color:red">(User[]) null</span>));
     *         
     *         <span style="color:green">//-------------------------------------------------</span>
     * 
     *         Set{@code <User>} set = new LinkedHashSet<>();
     *         set.add(null);
     * 
     *         assertEquals(list, toSet(<span style="color:red">(User) null</span>));
     *         </pre>
     * 
     *         否则返回 {@code new LinkedHashSet<T>(Arrays.asList(arrays));}
     * @see "com.google.common.collect.Sets#newHashSet(E...)"
     * @since 1.9.6
     */
    @SafeVarargs
    public static <T> Set<T> toSet(T...arrays){
        return isNullOrEmpty(arrays) ? Collections.<T> emptySet() : new LinkedHashSet<>(Arrays.asList(arrays));
    }

    //----------------------------toArray-----------------------------------

    /**
     * 将动态数组转成数组.
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * String[] array = ConvertUtil.toArray("1", "2");                  =   ["1", "2"];
     * 
     * String[] emptyArray = ConvertUtil.{@code <String>}toArray();     =   [] ; //= new String[] {};
     * Integer[] emptyArray = ConvertUtil.{@code <Integer>}toArray();   =   [] ; //= new Integer[] {};
     * 
     * <span style="color:red">//注意</span>
     * String[] nullArray = ConvertUtil.toArray(null)                   =   null;
     * ConvertUtil.toArray((String) null)                               =   new String[] { null }
     * </pre>
     * 
     * </blockquote>
     * 
     * <h3>注意:</h3>
     * 
     * <blockquote>
     * <p>
     * 数组是具体化的(reified),而泛型在运行时是被擦除的(erasure)。<br>
     * 数组是在运行时才去判断数组元素的类型约束,而泛型正好相反,在运行时,泛型的类型信息是会被擦除的,只有编译的时候才会对类型进行强化。
     * </p>
     * 
     * <b>泛型擦除的规则:</b>
     * 
     * <ol>
     * <li>所有参数化容器类都被擦除成非参数化的(raw type); 如 List{@code <E>}、List{@code <List<E>>}都被擦除成 List</li>
     * <li>所有参数化数组都被擦除成非参数化的数组;如 List{@code <E>}[],被擦除成 List[]</li>
     * <li>Raw type 的容器类,被擦除成其自身,如 List{@code <E>}被擦 除成 List</li>
     * <li>原生类型(int,String 还有 wrapper 类)都擦除成他们的自身</li>
     * <li>参数类型 E,如果没有上限,则被擦除成 Object</li>
     * <li>所有约束参数如{@code <? Extends E>}、{@code <X extends E>}都被擦 除成 E</li>
     * <li>如果有多个约束,擦除成第一个,如{@code <T extends Object & E>},则擦除成 Object</li>
     * </ol>
     * 
     * <p>
     * 这将会导致下面的代码:
     * </p>
     * 
     * <pre class="code">
     * 
     * public static {@code <K, V>} Map{@code <K, V[]>} toArrayValueMap(Map{@code <K, V>} singleValueMap){
     *     Map{@code <K, V[]>} arrayValueMap = newLinkedHashMap(singleValueMap.size());//保证顺序和参数singleValueMap顺序相同
     *     for (Map.Entry{@code <K, V>} entry : singleValueMap.entrySet()){
     *         arrayValueMap.put(entry.getKey(), toArray(entry.getValue()));//注意此处的Value不要声明成V,否则会变成Object数组
     *     }
     *     return arrayValueMap;
     * }
     * </pre>
     * 
     * 调用的时候,
     * 
     * <pre class="code">
     * Map{@code <String, String>} singleValueMap = MapUtil.newLinkedHashMap(2);
     * singleValueMap.put("province", "江苏省");
     * singleValueMap.put("city", "南通市");
     * 
     * Map{@code <String, String[]>} arrayValueMap = MapUtil.toArrayValueMap(singleValueMap);
     * String[] strings = arrayValueMap.get("province");//此时返回的是 Object[]
     * </pre>
     * 
     * 会出现异常
     * 
     * <pre class="code">
     * java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
     * </pre>
     * 
     * </blockquote>
     *
     * @param <T>
     *            the generic type
     * @param arrays
     *            the arrays
     * @return 如果 <code>arrays</code> 是null,返回null<br>
     * @see org.apache.commons.lang3.ArrayUtils#toArray(Object...)
     * @since commons-lang 3
     * @since 1.6.0
     */
    @SafeVarargs
    public static <T> T[] toArray(T...arrays){
        return ArrayUtils.toArray(arrays);
    }

    /**
     * 将集合 <code>collection</code> 转成数组.
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * List{@code <String>} list = new ArrayList{@code <>}();
     * list.add("xinge");
     * list.add("feilong");
     * </pre>
     * 
     * 以前你需要写成:
     * 
     * <pre class="code">
     * list.toArray(new String[list.size()]);
     * </pre>
     * 
     * 现在你只需要写成:
     * 
     * <pre class="code">
     * String[] array = ConvertUtil.toArray(list, String.class);
     * LOGGER.info(JsonUtil.format(array));
     * </pre>
     * 
     * <b>返回:</b>
     * 
     * <pre class="code">
     * ["xinge","feilong"]
     * </pre>
     * 
     * </blockquote>
     *
     * @param <T>
     *            the generic type
     * @param collection
     *            collection
     * @param arrayComponentType
     *            数组组件类型的 Class
     * @return 如果 <code>collection</code> 是null,直接返回null<br>
     *         如果 <code>arrayComponentType</code> 是null,抛出 {@link NullPointerException}<br>
     * @see java.lang.reflect.Array#newInstance(Class, int)
     * @see java.lang.reflect.Array#newInstance(Class, int...)
     * @see java.util.Collection#toArray()
     * @see java.util.Collection#toArray(Object[])
     * @see java.util.List#toArray()
     * @see java.util.List#toArray(Object[])
     * @see java.util.Vector#toArray()
     * @see java.util.Vector#toArray(Object[])
     * @see java.util.LinkedList#toArray()
     * @see java.util.LinkedList#toArray(Object[])
     * @see java.util.ArrayList#toArray()
     * @see java.util.ArrayList#toArray(Object[])
     * 
     * @see org.apache.commons.collections4.IteratorUtils#toArray(Iterator,Class)
     * @see "org.springframework.util.StringUtils#toStringArray(Collection)"
     * @since 1.2.2
     */
    public static <T> T[] toArray(Collection<T> collection,Class<T> arrayComponentType){
        if (null == collection){ // since 1.8.6
            return null;
        }

        Validate.notNull(arrayComponentType, "arrayComponentType must not be null");

        // 如果采用大家常用的把a的length设为0,就需要反射API来创建一个大小为size的数组,而这对性能有一定的影响.
        // 所以最好的方式就是直接把a的length设为Collection的size从而避免调用反射API来达到一定的性能优化.
        T[] array = ArrayUtil.newArray(arrayComponentType, collection.size());

        //注意,toArray(new Object[0]) 和 toArray() 在功能上是相同的. 
        return collection.toArray(array);
    }

    /**
     * 将字符串数组 <code>toBeConvertedValue</code> 转成指定类型 <code>targetType</code> 的数组.
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * String[] ss = { "2", "1" };
     * toArray(ss, Long.class);                                     =   new Long[] { 2L, 1L }
     * 
     * ConvertUtil.toArray((String[]) null, Serializable.class)     =   null
     * </pre>
     * 
     * </blockquote>
     *
     * @param <T>
     *            the generic type
     * @param toBeConvertedValue
     *            the values
     * @param targetType
     *            要被转换的目标类型
     * @return 如果 <code>toBeConvertedValue</code> 是null,那么返回null<br>
     *         如果 <code>targetType</code> 是null,抛出 {@link NullPointerException}<br>
     *         否则调用 {@link ConvertUtils#convert(String[], Class)}
     * @see org.apache.commons.beanutils.ConvertUtils#convert(String[], Class)
     * @see org.apache.commons.beanutils.ConvertUtilsBean#convert(String[], Class)
     * @since 1.6.0
     */
    @SuppressWarnings("unchecked")
    public static <T> T[] toArray(String[] toBeConvertedValue,Class<T> targetType){
        //如果指定的类型 本身就是数组类型的class,那么返回的类型就是该数组类型,否则将基于指定类型构造数组.
        return null == toBeConvertedValue ? null : (T[]) ConvertUtils.convert(toBeConvertedValue, targetType);
    }

    //---------------------------------------------------------------

    /**
     * 将 <code>toBeConvertedValue</code> 转成{@link String}数组.
     * 
     * <h3>说明:</h3>
     * 
     * <blockquote>
     * 
     * <ol>
     * 
     * <li>
     * 
     * <p>
     * 该方法很适合将 <b>非字符串数组的数组</b> 转换成 <b>字符串数组</b>,比如
     * </p>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * URL[] urls = {
     *                URLUtil.newURL("http://www.exiaoshuo.com/jinyiyexing0/"),
     *                URLUtil.newURL("http://www.exiaoshuo.com/jinyiyexing1/"),
     *                URLUtil.newURL("http://www.exiaoshuo.com/jinyiyexing2/"),
     *                null };
     * 
     * LOGGER.debug(JsonUtil.format(ConvertUtil.toStrings(urls)));
     * </pre>
     * 
     * <b>返回:</b>
     * 
     * <pre class="code">
     * [
     * "http://www.exiaoshuo.com/jinyiyexing0/",
     * "http://www.exiaoshuo.com/jinyiyexing1/",
     * "http://www.exiaoshuo.com/jinyiyexing2/",
     * null
     * ]
     * </pre>
     * 
     * <p>
     * 还有诸如 Integer[] 转成 String[]
     * </p>
     * 
     * <pre class="code">
     * ConvertUtil.toStrings(new Integer[] { 1, 2, 5 })     =   [ "1", "2", "5" ]
     * </pre>
     * 
     * </blockquote>
     * 
     * </li>
     * 
     * <li>
     * <p>
     * 也可以将字符串 解析成数组 in the Java language into a <code>List</code> individual Strings for each element, 根据以下规则:
     * </p>
     * 
     * <h3>字符串转成数组的规则:</h3>
     * 
     * <blockquote>
     * 
     * <p>
     * 参见 {@link org.apache.commons.beanutils.converters.AbstractArrayConverter#parseElements(String) parseElements}
     * </p>
     * 
     * <ul>
     * <li>The string is expected to be a comma-separated list of values.</li>
     * <li>自动去除开头的 <b>'{'</b> 和 结束的<b>'}'</b>.</li>
     * <li>每个元素前后的<b>空格将会去除</b>.</li>
     * <li>Elements in the list may be delimited by single or double quotes.
     * Within a quoted elements, the normal Java escape sequences are valid.</li>
     * </ul>
     * 
     * <p>
     * 示例:
     * </p>
     * 
     * <pre class="code">
     * ConvertUtil.toStrings("{5,4, 8,2;8 [email protected]`a}"); =  ["5","4","8","2","8","9","5","3","a"]
     * </pre>
     * 
     * </blockquote>
     * 
     * </li>
     * </ol>
     * 
     * </blockquote>
     * 
     * @param toBeConvertedValue
     *            the to be converted value
     * @return 如果 <code>toBeConvertedValue</code> 是null,返回null<br>
     * @see org.apache.commons.beanutils.converters.ArrayConverter#convertToType(Class, Object)
     * @see org.apache.commons.beanutils.converters.ArrayConverter#parseElements(Class, String)
     * @see #convert(Object, Class)
     * @since 1.4.0
     */
    public static String[] toStrings(Object toBeConvertedValue){
        return convert(toBeConvertedValue, String[].class);
    }

    /**
     * 将 <code>toBeConvertedValue</code>转成{@link Iterator}类型.
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * <span style="color:green">// null</span>
     * toIterator(null) = null
     * 
     * <span style="color:green">//PrimitiveArray</span>
     * int[] i2 = { 1, 2 };
     * Iterator{@code <Integer>} iterator = toIterator(i2);
     * 
     * <span style="color:green">//逗号分隔的字符串</span>
     * Iterator{@code <String>} iterator = toIterator("1,2");
     * 
     * <span style="color:green">//collection</span>
     * List{@code <String>} list = new ArrayList{@code <>}();
     * list.add("aaaa");
     * list.add("nnnnn");
     * 
     * Iterator{@code <String>} iterator = toIterator(list);
     * 
     * <span style="color:green">//Enumeration</span>
     * Enumeration{@code <Object>} enumeration = new StringTokenizer("this is a test");
     * Iterator{@code <String>} iterator = toIterator(enumeration);
     * 
     * </pre>
     * 
     * </blockquote>
     * 
     * <h3>支持以下类型:</h3>
     * 
     * <blockquote>
     * <ul>
     * <li>逗号分隔的字符串,先使用{@link ConvertUtil#toStrings(Object)} 转成数组</li>
     * <li>数组(包括 包装类型数组 以及 原始类型数组)</li>
     * <li>如果是{@link java.util.Map},将 {@link java.util.Map#values()} 转成{@link java.util.Iterator}</li>
     * <li>{@link java.util.Collection}</li>
     * <li>{@link java.util.Iterator}</li>
     * <li>{@link java.util.Enumeration}</li>
     * <li>{@link java.util.Dictionary}</li>
     * <li>{@link org.w3c.dom.Node}</li>
     * <li>{@link org.w3c.dom.NodeList}</li>
     * </ul>
     * </blockquote>
     *
     * @param <T>
     *            the generic type
     * @param toBeConvertedValue
     *            the to be converted value
     * @return 如果 <code>toBeConvertedValue</code> 是null,返回null<br>
     *         如果 <code>toBeConvertedValue</code> 是字符串,先转成数组,再转成迭代器<br>
     *         否则转成 {@link IteratorUtils#getIterator(Object)}
     * @see Collection#iterator()
     * @see EnumerationIterator#EnumerationIterator(Enumeration)
     * @see IteratorUtils#asIterator(Enumeration)
     * @see IteratorUtils#getIterator(Object)
     * @see "org.apache.taglibs.standard.tag.common.core.ForEachSupport#supportedTypeForEachIterator(Object)"
     * @since Commons Collections4.0
     */
    @SuppressWarnings("unchecked")
    public static <T> Iterator<T> toIterator(Object toBeConvertedValue){
        if (null == toBeConvertedValue){
            return null;
        }
        // 逗号分隔的字符串
        if (toBeConvertedValue instanceof String){
            return toIterator(toStrings(toBeConvertedValue));
        }
        return (Iterator<T>) IteratorUtils.getIterator(toBeConvertedValue);
    }

    /**
     * 将 <code>toBeConvertedValue</code> 转成指定 <code>targetType</code> 类型的对象.
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * ConvertUtil.convert("1", Integer.class)      =1
     * ConvertUtil.convert("", Integer.class)       =0
     * ConvertUtil.convert("1", Long.class)         =1
     * </pre>
     * 
     * </blockquote>
     * 
     * <h3>此外,该方法特别适合数组类型的转换,比如 Type[] 转成 Class []:</h3>
     * 
     * <blockquote>
     * 
     * 原来的写法:
     * 
     * <pre class="code">
     * 
     * Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
     * int length = actualTypeArguments.length;
     * Class{@code <?>}[] klasses = new Class{@code <?>}[length];
     * for (int i = 0, j = length; i {@code <} j; ++i){
     *     klasses[i] = (Class{@code <?>}) actualTypeArguments[i];
     * }
     * 
     * return klasses;
     * 
     * </pre>
     * 
     * 现在可以重构成:
     * 
     * <pre class="code">
     * Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
     * return convert(actualTypeArguments, Class[].class);
     * </pre>
     * 
     * </blockquote>
     * 
     * <h3>注意:</h3>
     * 
     * <blockquote>
     * 
     * <ol>
     * 
     * <li>如果<code>targetType</code>的转换器没有注册,<b>那么传入的value原样返回</b>,<br>
     * 比如<code>ConvertUtil.convert("zh_CN", Locale.class)</code> 由于找不到converter,那么返回"zh_CN".
     * </li>
     * 
     * <li>如果转换不了,会使用默认值</li>
     * 
     * <li>如果传的 <code>toBeConvertedValue</code>是 <code>toBeConvertedValue.getClass().isArray()</code> 或者 {@link Collection}
     * <blockquote>
     * 
     * <dl>
     * <dt>如果 <code>targetType</code> 不是数组</dt>
     * <dd>
     * <p>
     * 那么<span style="color:red">会取第一个元素</span>进行转换,<br>
     * 参见{@link AbstractConverter#convert(Class, Object)},调用的 {@link AbstractConverter#convertArray(Object)} 方法
     * </p>
     * </dd>
     * 
     * <dt>如果 <code>targetType</code> 是数组</dt>
     * <dd>参见 {@link org.apache.commons.beanutils.converters.ArrayConverter#convertToType(Class, Object) ArrayConverter#convertToType(Class,
     * Object)} 会基于targetType 构造一个数组对象,大小长度就是 <code>toBeConvertedValue</code>的大小或者长度, 然后迭代 <code>toBeConvertedValue</code> 依次进行转换</dd>
     * 
     * </dl>
     * 
     * </blockquote>
     * </li>
     * </ol>
     * </blockquote>
     * 
     * 
     * <h3>注意:</h3>
     * 
     * <blockquote>
     * 
     * <p>
     * 该方法<b>不适合</b> list转换成字符串,比如:
     * </p>
     * 
     * <pre class="code">
     * ConvertUtil.toString(toList("张飞", "关羽", "", "赵云"), String.class) = "张飞"
     * </pre>
     * 
     * <p>
     * ,请使用 {@link #toString(Collection, ToStringConfig)}
     * </p>
     * 
     * <hr>
     * 
     * <p>
     * 该方法也<b>不适合</b> array 转换成字符串,比如:
     * </p>
     * 
     * <pre class="code">
     * Integer[] int1 = { 2, null, 1, null };
     * LOGGER.debug(ConvertUtil.toString(int1),String.class);        = 2
     * </pre>
     * 
     * <p>
     * 请使用 {@link #toString(Object[], ToStringConfig)}
     * </p>
     * 
     * </blockquote>
     * 
     * <h3>对于 Array 转成 String:</h3>
     * 
     * <blockquote>
     * 
     * <p>
     * 参见 {@link org.apache.commons.beanutils.converters.ArrayConverter#convertToString(Object) ArrayConverter#convertToString(Object)} <br>
     * 
     * 在转换的过程中,如果发现object是数组,将使用 {@link java.lang.reflect.Array#get(Object, int) Array#get(Object, int)}来获得数据,<br>
     * 如果发现不是数组,将会将object转成集合 {@link org.apache.commons.beanutils.converters.ArrayConverter#convertToCollection(Class, Object)
     * ArrayConverter#convertToCollection(Class, Object)}再转成迭代器 {@link java.util.Collection#iterator() Collection.iterator()}
     * </p>
     * 
     * <p>
     * 在将object转成集合 {@link org.apache.commons.beanutils.converters.ArrayConverter#convertToCollection(Class, Object)
     * ArrayConverter#convertToCollection(Class, Object)}时候,有以下规则:
     * </p>
     *
     * <ul>
     * <li>The string is expected to be a comma-separated list of values.</li>
     * <li>字符串可以被'{' and '}'分隔符包裹.</li>
     * <li>去除前后空白.</li>
     * <li>Elements in the list may be delimited by single or double quotes. Within a quoted elements, the normal Java escape sequences are
     * valid.</li>
     * </ul>
     * 
     * <p>
     * 默认:
     * </p>
     * 
     * <blockquote>
     * <table border="1" cellspacing="0" cellpadding="4" summary="">
     * 
     * <tr style="background-color:#ccccff">
     * <th align="left">字段</th>
     * <th align="left">说明</th>
     * </tr>
     * 
     * <tr valign="top">
     * <td>int defaultSize</td>
     * <td>指定构建的默认数组的大小 or if less than zero indicates that a <code>null</code> default value should be used.</td>
     * </tr>
     * 
     * <tr valign="top" style="background-color:#eeeeff">
     * <td>char delimiter = ','</td>
     * <td>分隔符,转成的string中的元素分隔符</td>
     * </tr>
     * 
     * <tr valign="top">
     * <td>char[] allowedChars = new char[] {'.', '-'}</td>
     * <td>用于{@link java.io.StreamTokenizer}分隔字符串</td>
     * </tr>
     * 
     * <tr valign="top" style="background-color:#eeeeff">
     * <td>boolean onlyFirstToString = true;</td>
     * <td>只转第一个值</td>
     * </tr>
     * 
     * </table>
     * </blockquote>
     * </blockquote>
     * 
     * @param <T>
     *            the generic type
     * @param toBeConvertedValue
     *            需要被转换的对象/值
     * @param targetType
     *            要转成什么类型
     * @return 如果 <code>targetType</code> 是null,抛出 {@link NullPointerException}<br>
     *         如果 <code>toBeConvertedValue</code> 是null,那么直接返回null<br>
     *         否则返回 {@link org.apache.commons.beanutils.ConvertUtils#convert(Object, Class)}
     * @see org.apache.commons.beanutils.ConvertUtils#convert(Object, Class)
     * @see org.apache.commons.beanutils.converters.AbstractConverter#convert(Class, Object)
     * @see org.apache.commons.beanutils.converters.ArrayConverter#convertToType(Class, Object)
     */
    @SuppressWarnings("unchecked")
    public static <T> T convert(Object toBeConvertedValue,Class<T> targetType){
        Validate.notNull(targetType, "targetType can't be null!");
        return null == toBeConvertedValue ? null : (T) ConvertUtils.convert(toBeConvertedValue, targetType);
    }

    //---------------------------------------------------------------

    /**
     * 将对象转成 {@link Locale}.
     * 
     * <h3>示例:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * ConvertUtil.toLocale(null)       = null
     * ConvertUtil.toLocale("zh_CN")    = Locale.CHINA
     * </pre>
     * 
     * </blockquote>
     *
     * @param locale
     *            可以是 <b>null</b> ,<b>字符串</b> 或者 直接的 {@link Locale}对象
     * @return 如果 <code>locale</code> 是null,返回 null<br>
     *         如果 <code>locale instanceof <span style="color:green">Locale</span></code>,返回 <code>(Locale) locale</code><br>
     *         如果 <code>locale instanceof <span style="color:green">String</span></code>,返回 {@link LocaleUtils#toLocale(String)}<br>
     *         其他的类型,将抛出 {@link UnsupportedOperationException}
     * @see org.apache.commons.lang3.LocaleUtils#toLocale(String)
     * @since 1.7.2
     */
    public static Locale toLocale(Object locale){
        if (null == locale){
            return null;
        }

        //---------------------------------------------------------------
        if (locale instanceof Locale){
            return (Locale) locale;
        }
        if (locale instanceof String){
            return LocaleUtils.toLocale((String) locale);
        }

        //---------------------------------------------------------------
        throw new UnsupportedOperationException("input param [locale] type is:[" + locale.getClass().getName() + "] not support!");
    }
}