com.discovery.darchrow.net.ParamUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.discovery.darchrow.net.ParamUtil.java

Source

/*
 * 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.discovery.darchrow.net;

import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.discovery.darchrow.bean.ConvertUtil;
import com.discovery.darchrow.lang.CharsetType;
import com.discovery.darchrow.lang.StringUtil;
import com.discovery.darchrow.util.MapUtil;
import com.discovery.darchrow.util.Validator;

/**
 * ??.
 * 
 * @author  2010-4-15 ?04:01:29
 */
public final class ParamUtil {

    /** The Constant LOGGER. */
    private static final Logger LOGGER = LoggerFactory.getLogger(ParamUtil.class);

    /** Don't let anyone instantiate this class. */
    private ParamUtil() {
        //AssertionError?. ?????. ???.
        //see Effective Java 2nd
        throw new AssertionError("No " + getClass().getName() + " instances for you!");
    }

    /**
     * ??,???. <br>
     * 
     * <ol>
     * <li>? a  z ?????? </li>
     * <li>????&??</li>
     * <li>?????.</li>
     * <li><span style="color:red">?: ???? encoding ?</span></li>
     * </ol>
     * 
     * <h3>??:</h3> <blockquote>
     * <ol>
     * <li>{@code if isNullOrEmpty(filePath)---->} return {@link org.apache.commons.lang3.StringUtils#EMPTY}</li>
     * <li>paramsMap to naturalOrderingMap(TreeMap)</li>
     * <li>for naturalOrderingMap's entrySet(),join key and value use =,join each entry use &</li>
     * </ol>
     * </blockquote>
     *
     * @param paramsMap
     *            ???
     * @return the string
     * @since 1.2.0
     */
    public static String toNaturalOrderingString(Map<String, String> paramsMap) {
        if (Validator.isNullOrEmpty(paramsMap)) {
            return StringUtils.EMPTY;
        }

        StringBuilder sb = new StringBuilder();

        Map<String, String> naturalOrderingMap = new TreeMap<String, String>(paramsMap);

        int i = 0;
        int size = naturalOrderingMap.size();
        for (Map.Entry<String, String> entry : naturalOrderingMap.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();

            sb.append(key + "=" + value);

            // ??? &
            if (i != size - 1) {
                sb.append("&");
            }
            ++i;
        }

        String naturalOrderingString = sb.toString();
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug(naturalOrderingString);
        }
        return naturalOrderingString;
    }

    // ************************************addParameter******************************************************

    /**
     * ? ???.
     * 
     * @param url
     *            the url
     * @param paramName
     *            ???
     * @param parameValue
     *            ?
     * @param charsetType
     *            the charset type
     * @return ? ???
     */
    public static String addParameter(String url, String paramName, Object parameValue, String charsetType) {
        URI uri = URIUtil.create(url, charsetType);
        return addParameter(uri, paramName, parameValue, charsetType);
    }

    /**
     * ?,uri????,?.
     * 
     * <h3>1:</h3>
     * <blockquote>
     * 
     * <pre class="code">
     * String beforeUrl = "www.baidu.com";
     * Map{@code <String, String>} keyAndArrayMap = new LinkedHashMap{@code <String, String>}();
     * 
     * keyAndArrayMap.put("province", "??");
     * keyAndArrayMap.put("city", "?");
     * 
     * LOGGER.info(ParamUtil.addParameterSingleValueMap(beforeUrl, keyAndArrayMap, CharsetType.UTF8));
     * </pre>
     * 
     * :
     * 
     * <pre class="code">
     * {@code www.baidu.com?province=%E6%B1%9F%E8%8B%8F%E7%9C%81&city=%E5%8D%97%E9%80%9A%E5%B8%82}
     * </pre>
     * 
     * </blockquote>
     * <h3>2:</h3>
     * <blockquote>
     * 
     * <pre class="code">
     * String beforeUrl = "www.baidu.com?a=b";
     * Map{@code <String, String>} keyAndArrayMap = new LinkedHashMap{@code <String, String>}();
     * 
     * keyAndArrayMap.put("province", "??");
     * keyAndArrayMap.put("city", "?");
     * 
     * LOGGER.info(ParamUtil.addParameterSingleValueMap(beforeUrl, keyAndArrayMap, CharsetType.UTF8));
     * </pre>
     * 
     * :
     * 
     * <pre class="code">
     * {@code www.baidu.com?a=b&province=%E6%B1%9F%E8%8B%8F%E7%9C%81&city=%E5%8D%97%E9%80%9A%E5%B8%82}
     * </pre>
     * 
     * </blockquote>
     *
     * @param uriString
     *            the uri string
     * @param singleValueMap
     *            singleValueMap param name value 
     * @param charsetType
     *            ??, {@link CharsetType}<br>
     *            <span style="color:green">null empty,?,?</span><br>
     *            ??,??,ie?chrome? url ,?
     * @return  <code>uriString</code> nullempty, {@link StringUtils#EMPTY}<br>
     * @see #addParameterArrayValueMap(String, Map, String)
     */
    public static String addParameterSingleValueMap(String uriString, Map<String, String> singleValueMap,
            String charsetType) {
        return addParameterArrayValueMap(uriString, MapUtil.toArrayValueMap(singleValueMap), charsetType);
    }

    /**
     * ?,uri????,?.
     * 
     * <p>
     *  ?<code>queryString</code> ?,??map,?? <code>arrayValueMap</code>;<br>
     *  {@link LinkedHashMap},??map?
     * </p>
     * 
     * <h3>1:</h3>
     * <blockquote>
     * 
     * <pre class="code">
     * String beforeUrl = "www.baidu.com";
     * Map{@code <String, String[]>} keyAndArrayMap = new LinkedHashMap{@code <String, String[]>}();
     * 
     * keyAndArrayMap.put("receiver", new String[] { "", "feilong" });
     * keyAndArrayMap.put("province", new String[] { "??" });
     * keyAndArrayMap.put("city", new String[] { "?" });
     * LOGGER.info(ParamUtil.addParameterArrayValueMap(beforeUrl, keyAndArrayMap, CharsetType.UTF8));
     * </pre>
     * 
     * :
     * 
     * <pre class="code">
     * {@code www.baidu.com?receiver=%E9%91%AB%E5%93%A5&receiver=feilong&province=%E6%B1%9F%E8%8B%8F%E7%9C%81&city=%E5%8D%97%E9%80%9A%E5%B8%82}
     * </pre>
     * 
     * </blockquote>
     * 
     * 
     * <h3>2:</h3>
     * <blockquote>
     * 
     * <pre class="code">
     * String beforeUrl = "www.baidu.com?a=b";
     * Map{@code <String, String[]>} keyAndArrayMap = new LinkedHashMap{@code <String, String[]>}();
     * keyAndArrayMap.put("province", new String[] { "??" });
     * keyAndArrayMap.put("city", new String[] { "?" });
     * LOGGER.info(ParamUtil.addParameterArrayValueMap(beforeUrl, keyAndArrayMap, CharsetType.UTF8));
     * </pre>
     * 
     * :
     * 
     * <pre class="code">
     * {@code www.baidu.com?a=b&province=%E6%B1%9F%E8%8B%8F%E7%9C%81&city=%E5%8D%97%E9%80%9A%E5%B8%82}
     * </pre>
     * 
     * </blockquote>
     *
     * @param uriString
     *            the uri string
     * @param arrayValueMap
     *            the name and array value map
     * @param charsetType
     *            ??, {@link CharsetType}<br>
     *            <span style="color:green">null empty,?,?</span><br>
     *            ??,??,ie?chrome? url ,?
     * @return ?,uri????,?<br>
     *          <code>uriString</code> nullempty, {@link StringUtils#EMPTY}<br>
     *          <code>arrayValueMap</code> nullempty, <code>uriString</code><br>
     * @see #addParameterArrayValueMap(URI, Map, String)
     * @since 1.4.0
     */
    public static String addParameterArrayValueMap(String uriString, Map<String, String[]> arrayValueMap,
            String charsetType) {
        return addParameterArrayValueMap(uriString, URIUtil.getQueryString(uriString), arrayValueMap, charsetType);
    }

    /**
     * ?.
     * 
     * <p>
     * uri????,?,?{@code a=1&a=2},a,[3,4],{@code a=3&a=4}.
     * </p>
     * 
     * @param uri
     *            ? ?,?,??,<br>
     *            ??, ?
     * @param arrayValueMap
     *            singleValueMap  request.getParameterMap
     * @param charsetType
     *            ??, {@link CharsetType}<br>
     *            <span style="color:green">null empty,?,?</span><br>
     *            ??,??,ie?chrome? url ,?
     * @return  <code>uri</code> null, {@link StringUtils#EMPTY}<br>
     */
    public static String addParameterArrayValueMap(URI uri, Map<String, String[]> arrayValueMap,
            String charsetType) {
        return null == uri ? StringUtils.EMPTY
                : addParameterArrayValueMap(uri.toString(), uri.getRawQuery(), arrayValueMap, charsetType);
    }

    /**
     * ? ???.
     * 
     * @param url
     *            the url
     * @param nameAndValuesMap
     *            nameAndValueMap param name value 
     * @param charsetType
     *            the charset type
     * @return ? ???
     */
    public static String addParameterArrayMap(String url, Map<String, String[]> nameAndValuesMap,
            String charsetType) {
        URI uri = URIUtil.create(url, charsetType);
        return addParameterArrayMap(uri, nameAndValuesMap, charsetType);
    }

    /**
     * ? ???.
     * 
     * @param url
     *            the url
     * @param nameAndValueMap
     *            nameAndValueMap param name value 
     * @param charsetType
     *            the charset type
     * @return the string
     */
    public static String addParameterValueMap(String url, Map<String, String> nameAndValueMap, String charsetType) {
        Map<String, String[]> keyAndArrayMap = new HashMap<String, String[]>();

        if (Validator.isNotNullOrEmpty(nameAndValueMap)) {
            for (Map.Entry<String, String> entry : nameAndValueMap.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                keyAndArrayMap.put(key, new String[] { value });
            }
        }
        return addParameterArrayMap(url, keyAndArrayMap, charsetType);
    }

    /**
     * ? ???.
     * 
     * @param uri
     *            URI ? (URI),<br>
     *            ? ?,?,??,<br>
     *            ??, ?
     * @param paramName
     *            ???
     * @param parameValue
     *            ?
     * @param charsetType
     *            ?
     * @return ? ???
     */
    public static String addParameter(URI uri, String paramName, Object parameValue, String charsetType) {
        Map<String, String[]> map = new HashMap<String, String[]>();
        map.put(paramName, new String[] { parameValue.toString() });
        return addParameterArrayMap(uri, map, charsetType);
    }

    /**
     * ? <br>
     * ?????a=1&a=2,a,[3,4] a=3&a=4.
     * 
     * @param uri
     *            URI ? (URI),<br>
     *            ? ?,?,??,<br>
     *            ??, ?
     * @param nameAndValueMap
     *            nameAndValueMap  request.getParameterMap
     * @param charsetType
     *            ?
     * @return ? ???
     */
    public static String addParameterArrayMap(URI uri, Map<String, String[]> nameAndValueMap, String charsetType) {
        if (null == uri) {
            throw new IllegalArgumentException("uri can not be null!");
        }
        if (Validator.isNullOrEmpty(nameAndValueMap)) {
            throw new IllegalArgumentException("nameAndValueMap can not be null!");
        }
        // ***********************************************************************
        String url = uri.toString();
        String before = URIUtil.getBeforePath(url);
        // ***********************************************************************
        // getQuery()  URI ??
        // getRawQuery()  URI ? URI ???? URI 
        String query = uri.getRawQuery();
        // ***********************************************************************
        Map<String, String[]> map = new LinkedHashMap<String, String[]>();
        // url??
        if (Validator.isNullOrEmpty(query)) {
            // nothing to do
        } else {
            Map<String, String[]> originalMap = URIUtil.parseQueryToArrayMap(query, null);
            map.putAll(originalMap);
        }
        map.putAll(nameAndValueMap);
        // **************************************************************
        return URIUtil.getEncodedUrlByArrayMap(before, map, charsetType);
    }

    // ********************************removeParameter*********************************************************************

    /**
     * ?.
     * 
     * @param url
     *            the url
     * @param paramName
     *            the param name
     * @param charsetType
     *            ?
     * @return the string
     */
    public static String removeParameter(String url, String paramName, String charsetType) {
        URI uri = URIUtil.create(url, charsetType);
        return removeParameter(uri, paramName, charsetType);
    }

    /**
     * ?.
     * 
     * @param uri
     *            the uri
     * @param paramName
     *            the param name
     * @param charsetType
     *            ?
     * @return the string
     */
    private static String removeParameter(URI uri, String paramName, String charsetType) {
        List<String> paramNameList = null;
        if (Validator.isNotNullOrEmpty(paramName)) {
            paramNameList = new ArrayList<String>();
            paramNameList.add(paramName);
        }
        return removeParameterList(uri, paramNameList, charsetType);
    }

    /**
     * ?.
     * 
     * @param url
     *            the url
     * @param paramNameList
     *            the param name list
     * @param charsetType
     *            ?
     * @return the string
     */
    public static String removeParameterList(String url, List<String> paramNameList, String charsetType) {
        URI uri = URIUtil.create(url, charsetType);
        return removeParameterList(uri, paramNameList, charsetType);
    }

    /**
     * ?.
     * 
     * @param uri
     *            the uri
     * @param paramNameList
     *            the param name list
     * @param charsetType
     *            ?
     * @return the string
     */
    public static String removeParameterList(URI uri, List<String> paramNameList, String charsetType) {
        if (null == uri) {
            return "";
        }
        String url = uri.toString();
        //  paramNameList null 
        if (Validator.isNullOrEmpty(paramNameList)) {
            return url;
        }
        // ***********************************************************************
        String before = URIUtil.getBeforePath(url);
        // ***********************************************************************
        //  URI ? URI ???? URI 
        String query = uri.getRawQuery();
        // ***********************************************************************
        // url??
        if (Validator.isNullOrEmpty(query)) {
            // ??
            return url;
        } else {
            Map<String, String[]> map = URIUtil.parseQueryToArrayMap(query, null);
            for (String paramName : paramNameList) {
                map.remove(paramName);
            }
            return URIUtil.getEncodedUrlByArrayMap(before, map, charsetType);
        }
    }

    // **************************************retentionParams********************************************************

    /**
     * url?? ?.
     * 
     * @param url
     *            the url
     * @param paramNameList
     *            the param name list
     * @param charsetType
     *            ?
     * @return the string
     */
    public static String retentionParamList(String url, List<String> paramNameList, String charsetType) {
        URI uri = URIUtil.create(url, charsetType);
        return retentionParamList(uri, paramNameList, charsetType);
    }

    /**
     * ??mapkey value ?,? url queryString.
     * 
     * <h3>?:</h3>
     * 
     * <blockquote>
     * <ul>
     * <li><span style="color:red">?encode?</span>,</li>
     * <li>map key??,???;,??</li>
     * </ul>
     * </blockquote>
     * 
     * <h3>:</h3>
     * <blockquote>
     * 
     * <pre class="code">
     * Map{@code <String, String[]>} keyAndArrayMap = new LinkedHashMap{@code <String, String[]>}();
     * 
     * keyAndArrayMap.put("province", new String[] { "??", "?" });
     * keyAndArrayMap.put("city", new String[] { "?" });
     * LOGGER.info(ParamUtil.joinArrayValueMap(keyAndArrayMap));
     * </pre>
     * 
     * :
     * 
     * <pre class="code">
     * {@code province=??&province=?&city=?}
     * </pre>
     * 
     * </blockquote>
     *
     * @param arrayValueMap
     *            the array value map
     * @return  <code>arrayValueMap</code>  NullEmpty, {@link StringUtils#EMPTY}<br>
     *         ? <code>arrayValueMap</code> ?QueryString
     * @see #joinParamNameAndValues(String, String[])
     * @see <a href="http://www.leveluplunch.com/java/examples/build-convert-map-to-query-string/">build-convert-map-to-query-string</a>
     * @since 1.5.5
     */
    public static String toQueryStringUseArrayValueMap(Map<String, String[]> arrayValueMap) {
        if (Validator.isNullOrEmpty(arrayValueMap)) {
            return StringUtils.EMPTY;
        }

        int i = 0;
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String[]> entry : arrayValueMap.entrySet()) {
            sb.append(joinParamNameAndValues(entry.getKey(), entry.getValue()));
            if (i != arrayValueMap.size() - 1) {// ?& ?
                sb.append(URIComponents.AMPERSAND);
            }
            ++i;
        }
        return sb.toString();
    }

    /**
     * url?? ?.
     * 
     * @param uri
     *            the uri
     * @param paramNameList
     *            the param name list
     * @param charsetType
     *            ?
     * @return the string
     */
    public static String retentionParamList(URI uri, List<String> paramNameList, String charsetType) {
        if (null == uri) {
            return "";
        } else {
            String url = uri.toString();
            //  paramNameList null 
            if (Validator.isNullOrEmpty(paramNameList)) {
                return url;
            }
            String before = URIUtil.getBeforePath(url);
            // ***********************************************************************
            //  URI ? URI ???? URI 
            String query = uri.getRawQuery();
            // ***********************************************************************
            // url??
            if (Validator.isNullOrEmpty(query)) {
                // ??
                return url;
            } else {
                Map<String, String[]> map = new LinkedHashMap<String, String[]>();

                Map<String, String[]> originalMap = URIUtil.parseQueryToArrayMap(query, null);

                for (String paramName : paramNameList) {
                    map.put(paramName, originalMap.get(paramName));
                }
                return URIUtil.getEncodedUrlByArrayMap(before, map, charsetType);
            }
        }
    }

    /**
     * {@code a=1&b=2}????map (charsetType ?nullempty  keyvalue).
     * 
     * <p>
     *  {@link LinkedHashMap},map?? <code>queryString</code> ??
     * </p>
     * 
     * <p>
     * ??:?? {@code &} , ?keyvalue  = ?
     * </p>
     * 
     * <h3>1:</h3>
     * <blockquote>
     * 
     * <pre class="code">
     * LOGGER.info(JsonUtil.format(ParamUtil.toSafeArrayValueMap("{@code a=1&b=2&a=5}", CharsetType.UTF8)));
     * </pre>
     * 
     * :
     * 
     * <pre class="code">
     {"a": [
             "1",
             "5"
         ],
         "b": ["2"]
      }
     * </pre>
     * 
     * <hr>
     * 
     * <pre class="code">
     * LOGGER.info(JsonUtil.format(ParamUtil.toSafeArrayValueMap("{@code a=&b=2&a}", CharsetType.UTF8)));
     * </pre>
     * 
     * :
     * 
     * <pre class="code">
     {"a": [
         "",
         ""
     ],
      "b": ["2"]
     }
     * </pre>
     * 
     * </blockquote>
     *
     * @param queryString
     *            {@code a=1&b=2}?,?{@code a=1&a=1}?, map
     * @param charsetType
     *            ??, {@link CharsetType}<br>
     *            <span style="color:green">null empty,?,?</span><br>
     *            ??,??,ie?chrome? url ,?
     * @return  <code>queryString</code> nullempty, {@link Collections#emptyMap()}<br>
     * @see org.apache.commons.lang3.ArrayUtils#add(Object[], Object)
     * @see com.feilong.core.lang.StringUtil#split(String, String)
     * @since 1.4.0
     */
    public static Map<String, String[]> toSafeArrayValueMap(String queryString, String charsetType) {
        if (Validator.isNullOrEmpty(queryString)) {
            return Collections.emptyMap();
        }

        String[] nameAndValueArray = StringUtil.split(queryString, URIComponents.AMPERSAND);
        int length = nameAndValueArray.length;

        Map<String, String[]> safeArrayValueMap = MapUtil.newLinkedHashMap(length);// LinkedHashMap ???
        for (int i = 0; i < length; ++i) {
            String[] tempArray = nameAndValueArray[i].split("=", 2);

            String key = decodeAndEncode(tempArray[0], charsetType);
            String value = tempArray.length == 2 ? tempArray[1] : StringUtils.EMPTY;//??,???,???
            value = decodeAndEncode(value, charsetType);

            safeArrayValueMap.put(key, ArrayUtils.add(safeArrayValueMap.get(key), value));
        }
        return safeArrayValueMap;
    }

    /**
     * map?? queryString.
     * 
     * <p>
     * queryString??,singleValueMap key?,? {@link TreeMap},{@link LinkedHashMap}??
     * </p>
     * 
     * <h3>:</h3>
     * <blockquote>
     * 
     * map,
     * 
     * <pre class="code">
     * Map{@code <String, String[]>} keyAndArrayMap = new HashMap{@code <String, String[]>}();
     * keyAndArrayMap.put("name", new String[] { "jim", "feilong", "" });
     * keyAndArrayMap.put("age", new String[] { "18" });
     * keyAndArrayMap.put("love", new String[] { "sanguo" });
     * </pre>
     * 
     * :
     * 
     * <pre class="code">
     * LOGGER.info(ParamUtil.toSafeQueryString(keyAndArrayMap, CharsetType.UTF8));
     * </pre>
     * 
     * :
     * 
     * <pre class="code">
     * {@code love=sanguo&age=18&name=jim&name=feilong&name=%E9%91%AB%E5%93%A5}
     * </pre>
     * 
     * :
     * 
     * <pre class="code">
     * LOGGER.info(ParamUtil.toSafeQueryString(keyAndArrayMap, null));
     * </pre>
     * 
     * :
     * 
     * <pre class="code">
     * {@code love=sanguo&age=18&name=jim&name=feilong&name=}
     * </pre>
     * 
     * </blockquote>
     *
     * @param arrayValueMap
     *             <code>request.getParamMap</code>
     * @param charsetType
     *            ??, {@link CharsetType}<br>
     *            <span style="color:green">null empty,?,?</span><br>
     *            ??,??,ie?chrome? url ,?
     * @return  <code>arrayValueMap</code> nullempty, {@link StringUtils#EMPTY}<br>
     * @see #toQueryStringUseArrayValueMap(Map)
     * @since 1.4.0
     */
    public static String toSafeQueryString(Map<String, String[]> arrayValueMap, String charsetType) {
        return toQueryStringUseArrayValueMap(toSafeArrayValueMap(arrayValueMap, charsetType));
    }

    /**
     *  parameter array value map.
     * 
     * <p>
     *  <code>queryString</code> ??,??map,?? <code>arrayValueMap</code>;<br>
     *  {@link LinkedHashMap},??map?
     * </p>
     * 
     * @param uriString
     *            the uri string
     * @param queryString
     *            the query
     * @param arrayValueMap
     *            the name and array value map
     * @param charsetType
     *            ??, {@link CharsetType}<br>
     *            <span style="color:green">null empty,?,?</span><br>
     *            ??,??,ie?chrome? url ,?
     * @return the string
     * @since 1.4.0
     */
    private static String addParameterArrayValueMap(String uriString, String queryString,
            Map<String, String[]> arrayValueMap, String charsetType) {
        Map<String, String[]> safeArrayValueMap = ObjectUtils.defaultIfNull(arrayValueMap,
                Collections.<String, String[]>emptyMap());

        Map<String, String[]> arrayParamValuesMap = MapUtil.newLinkedHashMap(safeArrayValueMap.size());
        //???queryString map
        if (Validator.isNotNullOrEmpty(queryString)) {
            arrayParamValuesMap.putAll(toSafeArrayValueMap(queryString, null));
        }
        arrayParamValuesMap.putAll(safeArrayValueMap);
        return combineUrl(URIUtil.getFullPathWithoutQueryString(uriString), arrayParamValuesMap, charsetType);
    }

    /**
     * ?queryString()?(?);chromequery encoded???;ie????.
     * 
     * <p>
     * ??encoded,decode?encode;
     * </p>
     * 
     * <p>
     * ?decode(query,charsetType),? =
     * </p>
     *
     * @param value
     *            the value
     * @param charsetType
     *            ??, {@link CharsetType}<br>
     *            <span style="color:green">null empty,?,?</span><br>
     *            ??,??,ie?chrome? url ,?
     * @return  <code>value</code> nullempty, {@link StringUtils#EMPTY}<br>
     *         <code>charsetType</code> nullempty, <code>value</code><br>
     *         ? {@link URIUtil#decode(String, String)} ? {@link URIUtil#encode(String, String)}
     * @see <a
     *      href="http://stackoverflow.com/questions/15004593/java-request-getquerystring-value-different-between-chrome-and-ie-browser">
     *      java-request-getquerystring-value-different-between-chrome-and-ie-browser</a>
     * @since 1.4.0
     */
    private static String decodeAndEncode(String value, String charsetType) {
        if (Validator.isNullOrEmpty(value)) {
            return StringUtils.EMPTY;
        }
        return Validator.isNullOrEmpty(charsetType) ? value
                : URIUtil.encode(URIUtil.decode(value, charsetType), charsetType);
    }

    /**
     * url.
     *
     * @param beforePathWithoutQueryString
     *            the before path without query string
     * @param arrayValueMap
     *            the array value map
     * @param charsetType
     *            ??, {@link CharsetType}<br>
     *            <span style="color:green">null empty,?,?</span><br>
     *            ??,??,ie?chrome? url ,?
     * @return  <code>beforePathWithoutQueryString</code> nullempty, {@link StringUtils#EMPTY}<br>
     *         <code>arrayValueMap</code> nullempty, <code>beforePathWithoutQueryString</code>
     * @since 1.4.0
     */
    private static String combineUrl(String beforePathWithoutQueryString, Map<String, String[]> arrayValueMap,
            String charsetType) {
        if (Validator.isNullOrEmpty(beforePathWithoutQueryString)) {
            return StringUtils.EMPTY;
        }
        if (Validator.isNullOrEmpty(arrayValueMap)) {//? return
            return beforePathWithoutQueryString;
        }

        StringBuilder sb = new StringBuilder();
        sb.append(beforePathWithoutQueryString);
        sb.append(URIComponents.QUESTIONMARK);
        sb.append(toSafeQueryString(arrayValueMap, charsetType));

        return sb.toString();
    }

    /**
     * To safe array value map.
     * 
     * <p>
     *  {@link LinkedHashMap},??map?
     * </p>
     *
     * @param arrayValueMap
     *            the array value map
     * @param charsetType
     *            ??, {@link CharsetType}<br>
     *            <span style="color:green">null empty,?,?</span><br>
     *            ??,??,ie?chrome? url ,?
     * @return  <code>arrayValueMap</code> nullempty, {@link Collections#emptyMap()}<br>
     */
    private static Map<String, String[]> toSafeArrayValueMap(Map<String, String[]> arrayValueMap,
            String charsetType) {
        if (Validator.isNullOrEmpty(arrayValueMap)) {
            return Collections.emptyMap();
        }
        Map<String, String[]> safeArrayValueMap = MapUtil.newLinkedHashMap(arrayValueMap.size()); // LinkedHashMap,??map?
        for (Map.Entry<String, String[]> entry : arrayValueMap.entrySet()) {
            String key = entry.getKey();
            String[] paramValues = entry.getValue();
            if (Validator.isNullOrEmpty(paramValues)) {
                LOGGER.warn("the param key:[{}] value is null", key);
                paramValues = ArrayUtils.EMPTY_STRING_ARRAY;// empty,??
            }
            safeArrayValueMap.put(decodeAndEncode(key, charsetType), toSafeValueArray(paramValues, charsetType));
        }
        return safeArrayValueMap;
    }

    /**
     * To safe value array.
     *
     * @param paramValues
     *            the param values
     * @param charsetType
     *            the charset type
     * @return the string[]
     * @since 1.6.2
     */
    private static String[] toSafeValueArray(String[] paramValues, String charsetType) {
        if (Validator.isNullOrEmpty(charsetType)) {
            return paramValues;
        }
        List<String> paramValueList = new ArrayList<String>();
        for (String value : paramValues) {
            paramValueList.add(decodeAndEncode(value, charsetType));
        }
        return ConvertUtil.toArray(paramValueList, String.class);
    }

    /**
     * ??.
     * 
     * <p>
     * ,??? {@code paramName=name}, {@code paramValues  zhangfei,guanyu},{@code name=zhangfei&name=guanyu}
     * </p>
     * 
     * <h3>?:</h3>
     * <blockquote>
     * <ol>
     * <li>paramName ?  {@link StringUtils#defaultString(String)}???</li>
     * </ol>
     * </blockquote>
     *
     * @param paramName
     *            ???
     * @param paramValues
     *            ?
     * @return the string
     * @see java.lang.AbstractStringBuilder#append(String)
     * @see org.apache.commons.lang3.StringUtils#defaultString(String)
     * @see "org.springframework.web.servlet.view.RedirectView#appendQueryProperties(StringBuilder,Map, String)"
     * @since 1.4.0
     */
    private static String joinParamNameAndValues(String paramName, String[] paramValues) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0, j = paramValues.length; i < j; ++i) {
            //?: value null ,StringBuilder "null" , ?  java.lang.AbstractStringBuilder#append(String)
            sb.append(StringUtils.defaultString(paramName)).append("=")
                    .append(StringUtils.defaultString(paramValues[i]));
            if (i != j - 1) {// ?& ?
                sb.append(URIComponents.AMPERSAND);
            }
        }
        return sb.toString();
    }
}