com.sunchenbin.store.feilong.core.net.ParamUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.sunchenbin.store.feilong.core.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.sunchenbin.store.feilong.core.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.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sunchenbin.store.feilong.core.bean.ConvertUtil;
import com.sunchenbin.store.feilong.core.lang.CharsetType;
import com.sunchenbin.store.feilong.core.util.Validator;

/**
 * ??.
 * 
 * @author feilong
 * @version 1.0.0 2010-4-15 ?04:01:29
 * @version 1.4.0 2015-8-1 22:08
 * @since 1.0.0
 */
public final class ParamUtil {

    /** The Constant log. */
    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!");
    }

    /**
     * ?map???map.
     * 
     * <p style="color:green">
     *  {@link TreeMap},key?
     * </p>
     *
     * @param arrayValueMap
     *            the array value map
     * @return {@link TreeMap}
     * @since 1.4.0
     */
    public static Map<String, String> toSingleValueMap(Map<String, String[]> arrayValueMap) {// TreeMap log 
        if (Validator.isNullOrEmpty(arrayValueMap)) {
            return Collections.emptyMap();
        }

        Map<String, String> singleValueMap = new TreeMap<String, String>();
        for (Map.Entry<String, String[]> entry : arrayValueMap.entrySet()) {
            String key = entry.getKey();
            String[] values = entry.getValue();
            String singleValue = Validator.isNotNullOrEmpty(values) ? values[0] : StringUtils.EMPTY;
            singleValueMap.put(key, singleValue);
        }
        return singleValueMap;
    }

    /**
     * To array value map.
     * 
     * <p style="color:green">
     *  {@link TreeMap},key?
     * </p>
     * 
     * @param singleValueMap
     *            the name and value map
     * @return {@link TreeMap}
     * @since 1.4.0
     */
    public static Map<String, String[]> toArrayValueMap(Map<String, String> singleValueMap) {
        if (Validator.isNullOrEmpty(singleValueMap)) {
            return Collections.emptyMap();
        }

        Map<String, String[]> arrayValueMap = new TreeMap<String, String[]>();// TreeMap log 
        for (Map.Entry<String, String> entry : singleValueMap.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            arrayValueMap.put(key, new String[] { value });
        }
        return arrayValueMap;
    }

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

    /**
     * ?,uri????,?.
     *
     * @param uriString
     *            the uri string
     * @param paramName
     *            ???
     * @param parameValue
     *            ?
     * @param charsetType
     *            ??, {@link CharsetType}<br>
     *            <span style="color:green">null empty,?,?</span><br>
     *            ??,??,ie?chrome? url ,?
     * @return ?,uri????,?
     * @see #addParameter(URI, String, Object, String)
     */
    public static String addParameter(String uriString, String paramName, Object parameValue, String charsetType) {
        Map<String, String> singleValueMap = new HashMap<String, String>();
        singleValueMap.put(paramName, "" + parameValue);
        return addParameterSingleValueMap(uriString, singleValueMap, charsetType);
    }

    /**
     * ?,uri????,?.
     * 
     * @param uri
     *            ? ?,?,??,<br>
     *            ??, ?
     * @param paramName
     *            ???
     * @param parameValue
     *            ?
     * @param charsetType
     *            ??, {@link CharsetType}<br>
     *            <span style="color:green">null empty,?,?</span><br>
     *            ??,??,ie?chrome? url ,?
     * @return ?,uri????,?
     * @see #addParameterArrayValueMap(URI, Map, String)
     */
    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 });
        return addParameterArrayValueMap(uri, map, charsetType);
    }

    /**
     * ?,uri????,?.
     *
     * @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 the string
     * @see #addParameterArrayValueMap(String, Map, String)
     */
    public static String addParameterSingleValueMap(String uriString, Map<String, String> singleValueMap,
            String charsetType) {
        Map<String, String[]> arrayValueMap = toArrayValueMap(singleValueMap);
        return addParameterArrayValueMap(uriString, arrayValueMap, charsetType);
    }

    /**
     * ?,uri????,?.
     *
     * @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????,?
     * @see #addParameterArrayValueMap(URI, Map, String)
     * @since 1.4.0
     */
    public static String addParameterArrayValueMap(String uriString, Map<String, String[]> arrayValueMap,
            String charsetType) {
        //?  addParameterArrayValueMap(URI uri ,  uriString???uri
        if (null == uriString) {
            return StringUtils.EMPTY;
        }

        if (Validator.isNullOrEmpty(arrayValueMap)) {
            return uriString;
        }
        String queryString = URIUtil.getQueryString(uriString);
        return addParameterArrayValueMap(uriString, queryString, arrayValueMap, charsetType);
    }

    /**
     * ?.
     * 
     * <p>
     * uri????,?,?a=1&a=2,a,[3,4], 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 ?,uri????,?
     */
    public static String addParameterArrayValueMap(URI uri, Map<String, String[]> arrayValueMap,
            String charsetType) {
        if (null == uri) {
            return StringUtils.EMPTY;
        }

        String uriString = uri.toString();
        if (Validator.isNullOrEmpty(arrayValueMap)) {
            return uriString;
        }
        String queryString = uri.getRawQuery();
        return addParameterArrayValueMap(uriString, queryString, arrayValueMap, charsetType);
    }

    /**
     *  parameter array value map.
     *
     * @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[]> singleValueMap = new HashMap<String, String[]>();
        singleValueMap.putAll(arrayValueMap);
        if (Validator.isNotNullOrEmpty(queryString)) {
            // ? action before ??
            // "action": "https://202.6.215.230:8081/purchasing/purchase.do?action=loginRequest",
            // "fullEncodedUrl":"https://202.6.215.230:8081/purchasing/purchase.do?action=loginRequest?miscFee=0&descp=&klikPayCode=03BELAV220&transactionDate=23%2F03%2F2014+02%3A40%3A19&currency=IDR",
            Map<String, String[]> originalMap = toSafeArrayValueMap(queryString, null);
            singleValueMap.putAll(originalMap);
        }
        singleValueMap.putAll(arrayValueMap);
        return combineUrl(URIUtil.getFullPathWithoutQueryString(uriString), singleValueMap, charsetType);
    }

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

    /**
     * ?.
     *
     * @param uriString
     *            the uri string
     * @param paramName
     *            the param name
     * @param charsetType
     *            ??, {@link CharsetType}<br>
     *            <span style="color:green">null empty,?,?</span><br>
     *            ??,??,ie?chrome? url ,?
     * @return the string
     * @see #removeParameterList(String, List, String)
     */
    public static String removeParameter(String uriString, String paramName, String charsetType) {
        if (null == paramName) {
            return uriString;
        }
        List<String> list = new ArrayList<String>();
        list.add(paramName);
        return removeParameterList(uriString, list, charsetType);
    }

    /**
     * ?.
     * 
     * @param uri
     *            the uri
     * @param paramName
     *            the param name
     * @param charsetType
     *            ??, {@link CharsetType}<br>
     *            <span style="color:green">null empty,?,?</span><br>
     *            ??,??,ie?chrome? url ,?
     * @return the string
     * @see #removeParameterList(URI, List, String)
     */
    public static String removeParameter(URI uri, String paramName, String charsetType) {
        if (null == uri) {
            return StringUtils.EMPTY;
        }
        if (Validator.isNullOrEmpty(paramName)) {//  paramNameList null 
            return uri.toString();
        }
        List<String> paramNameList = new ArrayList<String>();
        paramNameList.add(paramName);

        return removeParameterList(uri, paramNameList, charsetType);
    }

    /**
     * ?.
     * 
     * @param uriString
     *            the url
     * @param paramNameList
     *            the param name list
     * @param charsetType
     *            ??, {@link CharsetType}<br>
     *            <span style="color:green">null empty,?,?</span><br>
     *            ??,??,ie?chrome? url ,?
     * @return the string
     */
    public static String removeParameterList(String uriString, List<String> paramNameList, String charsetType) {
        if (null == uriString) {
            return StringUtils.EMPTY;
        }
        if (Validator.isNullOrEmpty(paramNameList)) {//  paramNameList null 
            return uriString;
        }
        String queryString = URIUtil.getQueryString(uriString);
        return removeParameterList(uriString, queryString, paramNameList, charsetType);
    }

    /**
     * ?.
     * 
     * @param uri
     *            the uri
     * @param paramNameList
     *            the param name list
     * @param charsetType
     *            ??, {@link CharsetType}<br>
     *            <span style="color:green">null empty,?,?</span><br>
     *            ??,??,ie?chrome? url ,?
     * @return the string
     */
    public static String removeParameterList(URI uri, List<String> paramNameList, String charsetType) {
        if (null == uri) {
            return StringUtils.EMPTY;
        }
        String uriString = uri.toString();
        if (Validator.isNullOrEmpty(paramNameList)) {//  paramNameListnull
            return uriString;
        }
        String queryString = uri.getRawQuery();// URI? URI???? URI
        return removeParameterList(uriString, queryString, paramNameList, charsetType);
    }

    /**
     *  parameter list.
     *
     * @param uriString
     *            the uri string
     * @param queryString
     *            the query string
     * @param paramNameList
     *            the param name list
     * @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 removeParameterList(String uriString, String queryString, List<String> paramNameList,
            String charsetType) {
        if (Validator.isNullOrEmpty(uriString)) {
            return StringUtils.EMPTY;
        }
        if (Validator.isNullOrEmpty(queryString)) {
            return uriString;// ??
        }
        Map<String, String[]> singleValueMap = toSafeArrayValueMap(queryString, null);
        for (String paramName : paramNameList) {
            singleValueMap.remove(paramName);
        }
        return combineUrl(URIUtil.getFullPathWithoutQueryString(uriString), singleValueMap, charsetType);
    }

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

    /**
     * url???.
     *
     * @param uriString
     *            the uri string
     * @param paramNameList
     *            ?????list
     * @param charsetType
     *            ??, {@link CharsetType}<br>
     *            <span style="color:green">null empty,?,?</span><br>
     *            ??,??,ie?chrome? url ,?
     * @return the string
     * @see #retentionParamList(URI, List, String)
     */
    public static String retentionParamList(String uriString, List<String> paramNameList, String charsetType) {
        if (null == uriString) {
            return StringUtils.EMPTY;
        }

        if (Validator.isNullOrEmpty(paramNameList)) { //  paramNameList null 
            return uriString;
        }
        String queryString = URIUtil.getQueryString(uriString);
        return retentionParamList(uriString, queryString, paramNameList, charsetType);
    }

    /**
     * url???.
     * 
     * @param uri
     *            the uri
     * @param paramNameList
     *            ?????list
     * @param charsetType
     *            ??, {@link CharsetType}<br>
     *            <span style="color:green">null empty,?,?</span><br>
     *            ??,??,ie?chrome? url ,?
     * @return the string
     * @see #toSafeArrayValueMap(String, String)
     */
    public static String retentionParamList(URI uri, List<String> paramNameList, String charsetType) {
        if (null == uri) {
            return StringUtils.EMPTY;
        }

        String uriString = uri.toString();

        if (Validator.isNullOrEmpty(paramNameList)) { //  paramNameList null 
            return uriString;
        }
        String queryString = uri.getRawQuery(); //  URI? URI???? URI
        return retentionParamList(uriString, queryString, paramNameList, charsetType);
    }

    /**
     * ??.
     *
     * @param uriString
     *            the uri string
     * @param queryString
     *            the query string
     * @param paramNameList
     *            ?????list
     * @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 retentionParamList(String uriString, String queryString, List<String> paramNameList,
            String charsetType) {
        if (Validator.isNullOrEmpty(queryString)) {
            return uriString; //??
        }
        Map<String, String[]> originalArrayValueMap = toSafeArrayValueMap(queryString, null);

        Map<String, String[]> singleValueMap = new LinkedHashMap<String, String[]>();
        for (String paramName : paramNameList) {
            singleValueMap.put(paramName, originalArrayValueMap.get(paramName));
        }
        return combineUrl(URIUtil.getFullPathWithoutQueryString(uriString), singleValueMap, charsetType);
    }

    //*********************************************************************************

    /**
     * {@code a=1&b=2}????map (charsetType ?nullempty  keyvalue).
     *
     * @param queryString
     *            the query string
     * @param charsetType
     *            ??, {@link CharsetType}<br>
     *            <span style="color:green">null empty,?,?</span><br>
     *            ??,??,ie?chrome? url ,?
     * @return the {@code map<string, string>}
     * @see #toSafeArrayValueMap(String, String)
     * @since 1.4.0
     */
    public static Map<String, String> toSingleValueMap(String queryString, String charsetType) {
        Map<String, String[]> arrayValueMap = toSafeArrayValueMap(queryString, charsetType);
        return toSingleValueMap(arrayValueMap);
    }

    /**
     * {@code a=1&b=2}????map (charsetType ?nullempty  keyvalue).
     *
     * @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 a=1&b=2}????map (charsetType ?nullempty  keyvalue)
     * @since 1.4.0
     */
    public static Map<String, String[]> toSafeArrayValueMap(String queryString, String charsetType) {
        if (Validator.isNullOrEmpty(queryString)) {
            return Collections.emptyMap();
        }

        String[] nameAndValueArray = queryString.split(URIComponents.AMPERSAND);
        if (Validator.isNullOrEmpty(nameAndValueArray)) {
            return Collections.emptyMap();
        }

        Map<String, String[]> map = new LinkedHashMap<String, String[]>();
        for (int i = 0, j = nameAndValueArray.length; i < j; ++i) {
            String nameAndValue = nameAndValueArray[i];
            if (null != nameAndValue) {
                String[] tempArray = nameAndValue.split("=", 2);

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

                if (Validator.isNotNullOrEmpty(charsetType)) {
                    key = decodeAndEncode(key, charsetType);
                    value = decodeAndEncode(value, charsetType);
                }
                String[] valuesArrayInMap = map.get(key);

                List<String> list = null == valuesArrayInMap ? new ArrayList<String>()
                        : ConvertUtil.toList(valuesArrayInMap);
                list.add(value);

                map.put(key, ConvertUtil.toArray(list, String.class));
            }
        }
        return map;
    }

    /**
     * map?? queryString.
     * 
     * <p>
     * queryString??,singleValueMap key?,? {@link TreeMap},{@link LinkedHashMap}??
     * </p>
     *
     * @param arrayValueMap
     *             request.getParamMap
     * @param charsetType
     *            {@link CharsetType} ??,null empty,?,?<br>
     *            ??,??,ie?chrome ? url , ?
     * @return if isNullOrEmpty(appendMap) ,return ""
     * @see CharsetType
     * @see #toNaturalOrderingQueryString(Map)
     * @since 1.4.0
     */
    public static String toSafeQueryString(Map<String, String[]> arrayValueMap, String charsetType) {
        if (Validator.isNullOrEmpty(arrayValueMap)) {
            return StringUtils.EMPTY;
        }
        Map<String, String[]> safeArrayValueMap = toSafeArrayValueMap(arrayValueMap, charsetType);
        return joinArrayValueMap(safeArrayValueMap);
    }

    /**
     * To safe array value map.
     *
     * @param arrayValueMap
     *            the array value map
     * @param charsetType
     *            the charset type
     * @return if Validator.isNullOrEmpty(arrayValueMap) ,return emptyMap
     */
    private static Map<String, String[]> toSafeArrayValueMap(Map<String, String[]> arrayValueMap,
            String charsetType) {
        if (Validator.isNullOrEmpty(arrayValueMap)) {
            return Collections.emptyMap();
        }

        Map<String, String[]> safeArrayValueMap = new LinkedHashMap<String, String[]>();

        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,??
            }

            if (Validator.isNotNullOrEmpty(charsetType)) {
                key = decodeAndEncode(key, charsetType);
                List<String> paramValueList = new ArrayList<String>();
                for (String value : paramValues) {
                    paramValueList.add(Validator.isNotNullOrEmpty(value) ? decodeAndEncode(value, charsetType)
                            : StringUtils.EMPTY);
                }
                safeArrayValueMap.put(key, ConvertUtil.toArray(paramValueList, String.class));
            } else {
                safeArrayValueMap.put(key, paramValues);
            }
        }
        return safeArrayValueMap;
    }

    //*********************************************************************************************

    /**
     * ??,???.
     * 
     * <p style="color:red">
     * ?encode?,,?, ?
     * </p>
     * 
     * <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 StringUtils#EMPTY}</li>
     * <li>singleValueMap to naturalOrderingMap(TreeMap)</li>
     * <li>for naturalOrderingMap's entrySet(),join key and value use =,join each entry use &</li>
     * </ol>
     * </blockquote>
     *
     * @param singleValueMap
     *            ???
     * @return the string
     * @see #toSafeQueryString(Map, String)
     * @since 1.4.0
     */
    public static String toNaturalOrderingQueryString(Map<String, String> singleValueMap) {
        if (Validator.isNullOrEmpty(singleValueMap)) {
            return StringUtils.EMPTY;
        }
        Map<String, String> naturalParamsMapMap = new TreeMap<String, String>(singleValueMap);
        return joinSingleValueMap(naturalParamsMapMap);
    }

    /**
     * map?.
     * 
     * <p>
     * ,??? {@code paramName=name}, {@code paramValues  zhangfei},{@code name=zhangfei}
     * </p>
     *
     * @param singleValueMap
     *            the params map
     * @return the string
     * @see #toArrayValueMap(Map)
     * @see #joinArrayValueMap(Map)
     * @since 1.4.0
     */
    public static String joinSingleValueMap(Map<String, String> singleValueMap) {
        if (Validator.isNullOrEmpty(singleValueMap)) {
            return StringUtils.EMPTY;
        }
        Map<String, String[]> arrayValueMap = toArrayValueMap(singleValueMap);
        return joinArrayValueMap(arrayValueMap);
    }

    /**
     * ?keysvalue,?.
     * 
     * <p>
     * includeKeys?
     * </p>
     *
     * @param singleValueMap
     *            the map
     * @param includeKeys
     *            ?key
     * @return the mer data
     * @see org.apache.commons.lang3.StringUtils#defaultString(String)
     * @since 1.4.0
     */
    public static String joinValues(Map<String, String> singleValueMap, String... includeKeys) {
        if (Validator.isNullOrEmpty(singleValueMap)) {
            throw new NullPointerException("map can't be null/empty!");
        }
        StringBuilder sb = new StringBuilder();
        //??
        for (String key : includeKeys) {
            String value = singleValueMap.get(key);

            //value?, ?: value null ,StringBuilder "null" , ?  java.lang.AbstractStringBuilder#append(String)
            sb.append(StringUtils.defaultString(value));
        }
        return sb.toString();
    }

    /**
     * Join array value map.
     * 
     * <h3>?:</h3>
     * 
     * <blockquote>
     * <ul>
     * <li>?encode?,</li>
     * <li>map key??,???;,??</li>
     * </ul>
     * </blockquote>
     *
     * @param arrayValueMap
     *            the array value map
     * @return the string
     * @see #joinParamNameAndValues(String, String[])
     * @since 1.4.0
     */
    public static String joinArrayValueMap(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()) {
            String key = entry.getKey();
            String[] paramValues = entry.getValue();
            sb.append(joinParamNameAndValues(key, paramValues));

            if (i != arrayValueMap.size() - 1) {// ?& ?
                sb.append(URIComponents.AMPERSAND);
            }
            ++i;
        }
        return sb.toString();
    }

    /**
     * ??.
     * 
     * <p>
     * ,??? {@code paramName=name}, {@code paramValues  zhangfei,guanyu},{@code name=zhangfei&name=guanyu}
     * </p>
     *
     * @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) {
            String value = paramValues[i];
            //value?, ?: value null ,StringBuilder "null" , ?  java.lang.AbstractStringBuilder#append(String)
            sb.append(StringUtils.defaultString(paramName)).append("=").append(StringUtils.defaultString(value));
            if (i != j - 1) {// ?& ?
                sb.append(URIComponents.AMPERSAND);
            }
        }
        return sb.toString();
    }

    /**
     * ?queryString()?(?);chromequery encoded???;ie????.
     * 
     * <p>
     * ??encoded,decode?encode;
     * </p>
     * 
     * <p>
     * ?decode(query,charsetType),? =
     * </p>
     *
     * @param value
     *            the value
     * @param charsetType
     *            the charset type,pls use {@link CharsetType}
     * @return the 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;
        }
        if (Validator.isNullOrEmpty(charsetType)) {
            return value;
        }
        return URIUtil.encode(URIUtil.decode(value, charsetType), charsetType);
    }

    /**
     * Combine 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 the string
     * @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();
    }
}