package com.artfess.base.util;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import com.artfess.base.groovy.GroovyScriptEngine;
import com.artfess.base.util.string.StringPool;
import com.artfess.base.util.time.DateFormatUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.util.Assert;


/**
 * 字符串工具类
 *
 * @author heyifan
 * @company 阿特菲斯信息技术有限公司
 * @email heyf@jee-soft.cn
 * @date 2018年4月11日
 */
public class StringUtil {
    /**
     * 将字符串里面的所有英文点符号转成空格（字符实体形式）
     *
     * @param str 待处理的字符串
     * @return 每一个点对应一串：&nbsp;&emsp;
     */
    public static String convertPointToSpace(String str) {
        String space = "";
        if (StringUtils.isEmpty(str))
            return space;
        String path[] = str.split("\\.");
        for (int i = 0; i < path.length - 1; i++) {
            space += "&nbsp;&emsp;";
        }
        return space;
    }

    /**
     * 将输入流转utf-8字符串
     *
     * @param is 输入流
     * @return 字符串
     * @throws IOException
     */
    public static String InputStreamToString(InputStream is) throws IOException {
        ByteArrayOutputStream result = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int length;
        while ((length = is.read(buffer)) != -1) {
            result.write(buffer, 0, length);
        }
        String str = result.toString(StandardCharsets.UTF_8.name());
        result.close();
        return str;
    }

    /**
     * 把字符串数组转成带，的字符串
     *
     * @param arr
     * @return 返回字符串，格式如1,2,3
     */
    public static String join(String[] arr) {
        return join(arr, StringPool.COMMA);
    }

    /**
     * 把字符串数组转成带指定拆分字的字符串
     *
     * @param arr
     * @param split
     * @return String 返回字符串，格式如1,2,3
     * @since 1.0.0
     */
    public static String join(String[] arr, String split) {
        if (arr == null || arr.length == 0)
            return "";
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < arr.length; i++) {
            sb.append(arr[i]);
            sb.append(split);
        }
        return sb.substring(0, sb.length() - split.length());
    }

    /**
     * 把字符串类型的集合转成带，的字符串
     *
     * @param strs Collection<String> 适用于List、Set等。
     * @return
     */
    public static String join(Collection<String> strs) {
        return join(strs, StringPool.COMMA);
    }

    /**
     * /** 把字符串类型的集合转成指定拆分字符串的字符串
     *
     * @param strs  Collection<String> 适用于List、Set等。
     * @param split 拆分字符串
     * @return String
     * @since 1.0.0
     */
    public static String join(Collection<String> strs, String split) {
        if (strs == null || strs.isEmpty())
            return "";
        StringBuilder sb = new StringBuilder();
        Iterator<String> it = strs.iterator();
        while (it.hasNext()) {
            sb.append(it.next());
            sb.append(split);
        }
        return sb.substring(0, sb.length() - split.length());
    }

    /**
     * 将人民币金额数字转成中文大写。
     *
     * @param amount
     * @return
     */
    public static String convertToChineseNumeral(double amount) {
        char[] hunit = {'拾', '佰', '仟'}; // 段内位置表示
        char[] vunit = {'万', '亿'}; // 段名表示
        char[] digit = {'零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'}; // 数字表示
        long midVal = (long) (amount * 100); // 转化成整形
        String valStr = String.valueOf(midVal); // 转化成字符串

        String head = valStr.substring(0, valStr.length() - 2); // 取整数部分
        String rail = valStr.substring(valStr.length() - 2); // 取小数部分

        String prefix = ""; // 整数部分转化的结果
        String suffix = ""; // 小数部分转化的结果
        // 处理小数点后面的数
        if (rail.equals("00")) { // 如果小数部分为0
            suffix = "整";
        } else {
            suffix = digit[rail.charAt(0) - '0'] + "角"
                    + digit[rail.charAt(1) - '0'] + "分"; // 否则把角分转化出来
        }
        // 处理小数点前面的数
        char[] chDig = head.toCharArray(); // 把整数部分转化成字符数组
        char zero = '0'; // 标志'0'表示出现过0
        byte zeroSerNum = 0; // 连续出现0的次数
        for (int i = 0; i < chDig.length; i++) { // 循环处理每个数字
            int idx = (chDig.length - i - 1) % 4; // 取段内位置
            int vidx = (chDig.length - i - 1) / 4; // 取段位置
            if (chDig[i] == '0') { // 如果当前字符是0
                zeroSerNum++; // 连续0次数递增
                if (zero == '0') { // 标志
                    zero = digit[0];
                } else if (idx == 0 && vidx > 0 && zeroSerNum < 4) {
                    prefix += vunit[vidx - 1];
                    zero = '0';
                }
                continue;
            }
            zeroSerNum = 0; // 连续0次数清零
            if (zero != '0') { // 如果标志不为0,则加上,例如万,亿什么的
                prefix += zero;
                zero = '0';
            }
            prefix += digit[chDig[i] - '0']; // 转化该数字表示
            if (idx > 0) {
                prefix += hunit[idx - 1];
            }
            if (idx == 0 && vidx > 0) {
                prefix += vunit[vidx - 1]; // 段结束位置应该加上段名如万,亿
            }
        }

        if (prefix.length() > 0) {
            prefix += '圆'; // 如果整数部分存在,则有圆的字样
        }
        return prefix + suffix; // 返回正确表示
    }

    /**
     * 去除字符串里的html标签
     *
     * @param content 待转换的字符串
     * @return
     */
    public static String stripHtml(String content) {
        // <p>段落替换为换行
        content = content.replaceAll("<p .*?>", "\r\n");
        // <br><br/>替换为换行
        content = content.replaceAll("<br\\s*/?>", "\r\n");
        // 去掉其它的<>之间的东西
        content = content.replaceAll("\\<.*?>", "");
        // 去掉空格
        content = content.replaceAll(" ", "");
        return content;
    }

    /**
     * 将传入字符串中的Html字符实体（character entities）转换成Html预留字符
     *
     * @param content 待转换的字符串
     * @return
     */
    public static String convertCharEntityToHtml(String content) {
        content = content.replace("&apos;", "'").replace("&quot;", "\"")
                .replace("&gt;", ">").replace("&lt;", "<")
                .replace("&amp;", "&");

        int start = 0;
        int end = 0;
        final StringBuilder buffer = new StringBuilder();

        while (start > -1) {
            int system = 10;// 进制
            if (start == 0) {
                int t = content.indexOf("&#");
                if (start != t) {
                    start = t;
                }
                if (start > 0) {
                    buffer.append(content.substring(0, start));
                }
            }
            end = content.indexOf(";", start + 2);
            String charStr = "";
            if (end != -1) {
                charStr = content.substring(start + 2, end);
                // 判断进制
                char s = charStr.charAt(0);
                if (s == 'x' || s == 'X') {
                    system = 16;
                    charStr = charStr.substring(1);
                }
            }
            // 转换
            try {
                char letter = (char) Integer.parseInt(charStr, system);
                buffer.append(new Character(letter).toString());
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }

            // 处理当前unicode字符到下一个unicode字符之间的非unicode字符
            start = content.indexOf("&#", end);
            if (start - end > 1) {
                buffer.append(content.substring(end + 1, start));
            }

            // 处理最后面的非unicode字符
            if (start == -1) {
                int length = content.length();
                if (end + 1 != length) {
                    buffer.append(content.substring(end + 1, length));
                }
            }
        }
        return buffer.toString();
    }

    /**
     * 将传入的字符串的Html预留字符转换成Html字符实体（character entities）
     *
     * @param content 待转换的字符串（一般为Html代码）
     * @return
     */
    public static String convertHtmlToCharEntity(String content) {
        final StringBuilder sb = new StringBuilder();
        for (int i = 0; i < content.length(); i++) {
            char c = content.charAt(i);

            switch (c) {
                case 0x0A:
                    sb.append(c);
                    break;

                case '<':
                    sb.append("&lt;");
                    break;

                case '>':
                    sb.append("&gt;");
                    break;

                case '&':
                    sb.append("&amp;");
                    break;

                case '\'':
                    sb.append("&apos;");
                    break;

                case '"':
                    sb.append("&quot;");
                    break;

                default:
                    if ((c < ' ') || (c > 0x7E)) {
                        sb.append("&#x");
                        sb.append(Integer.toString(c, 16));
                        sb.append(';');
                    } else {
                        sb.append(c);
                    }
            }
        }
        return sb.toString();
    }

    /**
     * 格式化带参数的字符串，如 /param/detail.ht?a=${0}&b=${1}
     * 注意字符串的参数从0下标开始，字符串的参数数量和args数组的数量要一致。
     *
     * @param message
     * @param args
     * @return
     */
    public static String format(String message, Object... args) {
        for (int i = 0; i < args.length; i++) {
            message = message.replace("${" + i + "}", args[i].toString());
        }
        return message;
    }

    /**
     * 格式化如下字符串 http://www.bac.com?a=${a}&b=${b}
     *
     * @param message
     * @param params
     */
    public static String format(String message, Map<String, Object> params) {
        String result = message;
        if (params == null || params.isEmpty())
            return result;
        Iterator<String> keyIts = params.keySet().iterator();
        while (keyIts.hasNext()) {
            String key = keyIts.next();
            Object value = params.get(key);
            if (value != null) {
                result = result.replace("${" + key + "}", value.toString());
            }
        }
        return result;
    }

    /**
     * 简单的字符串格式化，性能较好。支持不多于10个占位符，从%1开始计算，数目可变。参数类型可以是字符串、Integer、Object，
     * 甚至int等基本类型
     * 、以及null，但只是简单的调用toString()，较复杂的情况用String.format()。每个参数可以在表达式出现多次。
     *
     * @param msgWithFormat
     * @param autoQuote     是否加中括号将结果括起来
     * @param args
     * @return
     */
    public static StringBuilder format(CharSequence msgWithFormat,
                                       boolean autoQuote, Object... args) {
        int argsLen = args.length;
        boolean markFound = false;

        StringBuilder sb = new StringBuilder(msgWithFormat);

        if (argsLen > 0) {
            for (int i = 0; i < argsLen; i++) {
                String flag = "%" + (i + 1);
                int idx = sb.indexOf(flag);
                // 支持多次出现、替换的代码
                while (idx >= 0) {
                    markFound = true;
                    sb.replace(idx, idx + 2, toString(args[i], autoQuote));
                    idx = sb.indexOf(flag);
                }
            }

            if (args[argsLen - 1] instanceof Throwable) {
                StringWriter sw = new StringWriter();
                ((Throwable) args[argsLen - 1])
                        .printStackTrace(new PrintWriter(sw));
                sb.append("\n").append(sw.toString());
            } else if (argsLen == 1 && !markFound) {
                sb.append(args[argsLen - 1].toString());
            }
        }
        return sb;
    }

    /**
     * 判断指定的内容是否存在
     *
     * @param content  内容
     * @param beginStr 开始内容
     * @param endStr   结束内容
     * @return
     */
    public static boolean isExist(String content, String beginStr, String endStr) {
        final boolean isExist = true;
        // 转成小写
        String lowContent = content.toLowerCase();
        String lowBeginStr = beginStr.toLowerCase();
        String lowEndStr = endStr.toLowerCase();

        int beginIndex = lowContent.indexOf(lowBeginStr);
        int endIndex = lowContent.indexOf(lowEndStr);
        if (beginIndex != -1 && endIndex != -1 && beginIndex < endIndex) {
            return isExist;
        }
        return !isExist;
    }

    /**
     * 对字符串去掉前面的指定字符
     *
     * @param content 待处理的字符串
     * @param prefix  要去掉前面的指定字符串
     * @return
     */
    public static String trimPrefix(String content, String prefix) {
        String resultStr = content;
        while (resultStr.startsWith(prefix)) {
            resultStr = resultStr.substring(prefix.length());
        }
        return resultStr;
    }

    /**
     * 对字符串去掉前面的指定字符
     *
     * @param content 待处理的字符串
     * @param suffix  要去掉后面的指定字符串
     * @return
     */
    public static String trimSuffix(String content, String suffix) {
        String resultStr = content;
        while (resultStr.endsWith(suffix)) {
            resultStr = resultStr.substring(0,
                    resultStr.length() - suffix.length());
        }
        return resultStr;
    }

    /**
     * 对字符串的前后均去掉前面的指定字符
     *
     * @param content
     * @param trimStr
     * @return
     */
    public static String trim(String content, String trimStr) {
        return trimSuffix(trimPrefix(content, trimStr), trimStr);
    }

    /**
     * 把字符串的第一个字母转为大写
     *
     * @param str 字符串
     * @return
     */
    public static String upperFirst(String str) {
        return toFirst(str, true);
    }

    /**
     * 判断字符串非空
     *
     * @param str
     * @return
     */
    public static boolean isNotEmpty(String str) {
        return !isEmpty(str);
    }

    /**
     * 判断字符串是否为空
     *
     * @param str
     * @return
     */
    public static boolean isEmpty(String str) {

        if (str == null)
            return true;
        if (str.trim().equals(""))
            return true;
        if ("null".equals(str)) {
            return true;
        }
        return false;
    }

    /**
     * 判断Long是否为空
     *
     * @param value
     * @return
     */
    public static boolean isEmpty(Long value) {
        if (value == null)
            return true;
        if (value.longValue() == 0)
            return true;
        return false;
    }


    /**
     * 为空判断,0做空处理。
     * <pre>
     * 这里判断：
     * 1.字符串为NULL
     * 2.字符串为空串。
     * 3.字符串为0。
     * </pre>
     *
     * @param tmp
     * @return boolean
     */
    public static boolean isZeroEmpty(String tmp) {
        boolean isEmpty = StringUtil.isEmpty(tmp);
        if (isEmpty) return true;
        return "0".equals(tmp);
    }

    /**
     * 非空判断。
     *
     * @param tmp
     * @return boolean
     */
    public static boolean isNotZeroEmpty(String tmp) {
        return !isZeroEmpty(tmp);
    }

    /**
     * 把字符串的第一个字母转为小写
     *
     * @param str
     * @return
     */
    public static String lowerFirst(String str) {
        return toFirst(str, false);
    }

    /**
     * 把字符串的第一个字母转为大写或者小写
     *
     * @param str     字符串
     * @param isUpper 是否大写
     * @return
     */
    public static String toFirst(String str, boolean isUpper) {
        if (StringUtils.isEmpty(str))
            return "";
        char first = str.charAt(0);
        String firstChar = new String(new char[]{first});
        firstChar = isUpper ? firstChar.toUpperCase() : firstChar.toLowerCase();
        return firstChar + str.substring(1);
    }

    /**
     * 将content中所有{...}的替换为replace参数内容
     *
     * @param content 待替换的字符串
     * @param replace 替换的字符串
     * @return 替换后的字符串，如content=abc{aa}{bb} ； replace ="ff"，结果就是abcffff
     */
    public static String replaceVariable(String content, String replace) {
        return replaceVariable(content, replace, "\\{(.*?)\\}");
    }

    /**
     * 将content中所有符合regular正则表达式的内容替换为replace参数内容
     *
     * @param content 待替换的字符串
     * @param replace 替换的字符串
     * @param regular 正则表达式
     * @return 替换后的字符串。 如content=abc{aa}{bb} ； replace
     * ="ff"，regular="\\{(.*?)\\}"；结果就是abcffff
     */
    public static String replaceVariable(String content, String replace,
                                         String regular) {
        Pattern regex = Pattern.compile(regular);
        String result = content;
        Matcher regexMatcher = regex.matcher(result);
        while (regexMatcher.find()) {
            String toReplace = regexMatcher.group(0);
            result = result.replace(toReplace, replace);
            regexMatcher = regex.matcher(result);
        }
        return result;
    }

    /**
     * 对传入的字符串（content）进行变量值替换（map） 采用默认的正则表达式：\\{(.*?)\\}
     *
     * @param content 要处理的字符串
     * @param map     替换参数和值的集合
     * @return 替换后的字符串
     * @throws Exception
     */
    public static String replaceVariableMap(String content,
                                            Map<String, Object> map) throws Exception {
        return replaceVariableMap(content, map, "\\{(.*?)\\}");
    }

    /**
     * @param template 要处理的字符串
     * @param map      替换参数和值的集合
     * @param regular  正则表达式
     * @return 替换后的字符串
     * @throws Exception 如果template的某个
     */
    public static String replaceVariableMap(String template,
                                            Map<String, Object> map, String regular) throws Exception {
        Pattern regex = Pattern.compile(regular);
        Matcher regexMatcher = regex.matcher(template);
        while (regexMatcher.find()) {
            String key = regexMatcher.group(1);
            String toReplace = regexMatcher.group(0);
            String value = (String) map.get(key);
            if (value != null) {
                template = template.replace(toReplace, value);
            } else {
                throw new Exception("没有找到[" + key + "]对应的变量值，请检查表变量配置!");
            }
        }

        return template;
    }

    /**
     * 根据默认的特殊字符正则表达式去除特殊字符
     *
     * @param str
     * @return
     */
    public static String removeSpecial(String str)
            throws PatternSyntaxException {
        return removeByRegEx(str, StringPool.SPECIAL_REG_EX);
    }

    /**
     * 根据传入的字符串（参数str），通过正则表达式（参数regEx），去掉该表达式匹配的字符。
     *
     * @param str   待处理的字符串
     * @param regEx 正则表达式
     * @return
     * @throws PatternSyntaxException
     */
    public static String removeByRegEx(String str, String regEx)
            throws PatternSyntaxException {
        // 清除掉所有特殊字符
        Pattern p = Pattern.compile(StringPool.SPECIAL_REG_EX);
        Matcher m = p.matcher(str);
        return m.replaceAll("").trim();
    }

    /**
     * String转Byte数组
     *
     * @param str
     * @return
     */
    public static byte[] stringToBytes(String str) {
        byte digest[] = new byte[str.length() / 2];
        for (int i = 0; i < digest.length; i++) {
            String byteString = str.substring(2 * i, 2 * i + 2);
            int byteValue = Integer.parseInt(byteString, 16);
            digest[i] = (byte) byteValue;
        }

        return digest;
    }

    /**
     * Byte数组转String
     *
     * @param b
     * @return
     */
    public static String bytesToString(byte b[]) {
        StringBuffer hexString = new StringBuffer();
        for (int i = 0; i < b.length; i++) {
            String plainText = Integer.toHexString(0xff & b[i]);
            if (plainText.length() < 2) {
                plainText = "0" + plainText;
            }
            hexString.append(plainText);
        }
        return hexString.toString();
    }

    /**
     * 将对象转成格式化的字符串输出
     *
     * @param obj       任意对象
     * @param autoQuote 是否加中括号将结果括起来
     * @return
     */
    public static String toString(Object obj, boolean autoQuote) {
        StringBuilder sb = new StringBuilder();
        if (obj == null) {
            sb.append("NULL");
        } else {
            if (obj instanceof Object[]) {
                for (int i = 0; i < ((Object[]) obj).length; i++) {
                    sb.append(((Object[]) obj)[i]).append(", ");
                }
                if (sb.length() > 0) {
                    sb.delete(sb.length() - 2, sb.length());
                }
            } else {
                sb.append(obj.toString());
            }
        }
        if (autoQuote
                && sb.length() > 0
                && !((sb.charAt(0) == '[' && sb.charAt(sb.length() - 1) == ']') || (sb
                .charAt(0) == '{' && sb.charAt(sb.length() - 1) == '}'))) {
            sb.insert(0, "[").append("]");
        }
        return sb.toString();
    }

    /**
     * 字符串 编码转换
     *
     * @param str  字符串
     * @param from 原來的編碼
     * @param to   轉換后的編碼
     * @return
     */
    public static String encodingString(String str, String from, String to) {
        String result = str;
        try {
            result = new String(str.getBytes(from), to);
        } catch (Exception e) {
            result = str;
        }
        return result;
    }

    /**
     * <p>获取最后被截取后后面的字符串</p>
     *
     * <pre>
     * StringUtils.substringAfterLast(null, *)        = null
     * StringUtils.substringAfterLast("", *)          = ""
     * StringUtils.substringAfterLast(*, "")          = ""
     * StringUtils.substringAfterLast(*, null)        = ""
     * StringUtils.substringAfterLast("abc", "a")     = "bc"
     * StringUtils.substringAfterLast("abcba", "b")   = "a"
     * StringUtils.substringAfterLast("abc", "c")     = ""
     * StringUtils.substringAfterLast("a", "a")       = ""
     * StringUtils.substringAfterLast("a", "z")       = ""
     * StringUtils.substringAfterLast("a.b.c.d", ".") = "d"
     * </pre>
     */
    public static String substringAfterLast(String str, String separator) {
        return StringUtils.substringAfterLast(
                str, separator);
    }

    /**
     * <p>获取最后被截取后前面的字符串</p>
     *
     * <pre>
     * StringUtils.substringBeforeLast(null, *)       = null
     * StringUtils.substringBeforeLast("", *)         = ""
     * StringUtils.substringBeforeLast("abcba", "b")  = "abc"
     * StringUtils.substringBeforeLast("abc", "c")    = "ab"
     * StringUtils.substringBeforeLast("a", "a")      = ""
     * StringUtils.substringBeforeLast("a", "z")      = "a"
     * StringUtils.substringBeforeLast("a", null)     = "a"
     * StringUtils.substringBeforeLast("a", "")       = "a"
     * StringUtils.substringAfterLast("a.b.c.d", ".") = "a.b.c"
     * </pre>
     */
    public static String substringBeforeLast(String str, String separator) {
        return StringUtils.substringBeforeLast(
                str, separator);
    }

    /**
     * 删除后面指定的字符
     *
     * @param toTrim
     * @param trimStr
     * @return
     */
    public static String trimSufffix(String toTrim, String trimStr) {
        while (toTrim.endsWith(trimStr)) {
            toTrim = toTrim.substring(0, toTrim.length() - trimStr.length());
        }
        return toTrim;
    }

    /**
     * 将数据库字段名转为DataGrid字段名
     * isIgnoreFirst:是否忽略第一个字段不转大写
     *
     * @return
     */
    public static String convertDbFieldToField(String dbField) {
        return convertDbFieldToField(dbField, "_", true);
    }

    /**
     * 将数据库字段名转为DataGrid字段名,如 sys_data_ 转为sysData
     * symbol:间隔符号
     * isIgnoreFirst：是否忽略第一个单词的首字母转大写
     *
     * @return
     */
    public static String convertDbFieldToField(String dbField, String symbol, boolean isIgnoreFirst) {
        String result = "";
        if (dbField.startsWith(symbol)) dbField = dbField.substring(1);
        if (dbField.endsWith(symbol)) dbField = dbField.substring(0, dbField.length() - 1);
        String[] arr = dbField.split(symbol);
        for (int i = 0; i < arr.length; i++) {
            String str = arr[i];
            if (isIgnoreFirst && i != 0) {
                char oldChar = str.charAt(0);
                char newChar = (oldChar + "").toUpperCase().charAt(0);
                str = newChar + str.substring(1);
            }
            result += str;
        }
        return result;
    }

    /**
     * 把String 转换成指定的对象
     *
     * @param obj
     * @param type
     * @return
     */
    public static Object parserObject(Object obj, String type) {
        if (obj == null)
            return null;
        Object val = obj;
        try {
            String str = obj.toString();
            if (type.equalsIgnoreCase("string")) {
                val = str;
            } else if (type.equalsIgnoreCase("int")) {
                val = Integer.parseInt(str);
            } else if (type.equalsIgnoreCase("float")) {
                val = Float.parseFloat(str);
            } else if (type.equalsIgnoreCase("double")) {
                val = Double.parseDouble(str);
            } else if (type.equalsIgnoreCase("byte")) {
                val = Byte.parseByte(str);
            } else if (type.equalsIgnoreCase("short")) {
                val = Short.parseShort(str);
            } else if (type.equalsIgnoreCase("long")) {
                val = Long.parseLong(str);
            } else if (type.equalsIgnoreCase("boolean")) {
                if (StringUtils.isNumeric(str))
                    val = (Integer.parseInt(str) == 1 ? true : false);
                val = Boolean.parseBoolean(str);
            } else if (type.equalsIgnoreCase("date")) {
                val = DateFormatUtil.parse(str);
            } else {
                val = str;
            }
        } catch (Exception e) {
            // TODO: handle exception
        }
        return val;
    }

    /**
     * 把String 转换成指定的对象
     *
     * @param objStr
     * @param type
     * @return
     */
    public static Object parserObject(String objStr, Class<?> type) {
        if (StringUtil.isEmpty(objStr))
            return null;
        try {
            switch (type.getSimpleName()) {
                case "String":
                case "Boolean":
                case "Byte":
                case "Short":
                case "Integer":
                case "Long":
                case "Float":
                case "Double":
                    return type.getConstructor(String.class).newInstance(objStr);
                case "boolean":
                case "byte":
                case "short":
                case "int":
                case "long":
                case "float":
                case "double":
                    return parserObject(objStr, type.getSimpleName());
                case "Date":
                    return DateUtils.parseDate(objStr, new String[]{"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "HH:mm:ss"});
                case "LocalDate":
                    return DateFormatUtil.dateParse(objStr, "yyyy-MM-dd");
                case "LocalDateTime":
                    return DateFormatUtil.parseDateTime(objStr);
                default:
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 根据一串逗号分隔的字符串取得字符串形数组
     *
     * @param str
     * @return
     * @author zhaoxy
     */
    public static String[] getStringAryByStr(String str) {
        if (StringUtil.isEmpty(str))
            return null;
        String[] aryId = str.split(",");
        String[] lAryId = new String[aryId.length];
        for (int i = 0; i < aryId.length; i++) {
            lAryId[i] = (aryId[i]);
        }
        return lAryId;
    }

    public static String getHumpName(String columnName) {
        if ((columnName == null) || (columnName.length() == 0)) {
            return "";
        }
        columnName = columnName.toLowerCase();
        StringBuffer sb = new StringBuffer();
        String regex = "_";
        String addString = "";
        String[] sbArr = columnName.split(regex);
        if ((sbArr.length == 1) && (sbArr[0].length() == 1))
            sb.append(sbArr[0]);
        else {
            for (int i = 0; i < sbArr.length; i++) {
                if (i == 0) {
                    if (sbArr[i].length() == 1)
                        addString = sbArr[i].toUpperCase();
                    else {
                        addString = sbArr[i];
                    }
                } else if (sbArr[i].length() == 1)
                    addString = sbArr[i].toUpperCase();
                else {
                    addString = sbArr[i].substring(0, 1).toUpperCase()
                            + sbArr[i].substring(1, sbArr[i].length());
                }

                sb.append(addString);
            }
        }
        return sb.toString();
    }

    /**
     * 根据一串逗号分隔的长整型字符串取得长整形数组
     *
     * @param str 字符串参数
     * @return 返回长整型数组
     */
    public static Long[] getLongAryByStr(String str) {
        if (StringUtil.isEmpty(str))
            return null;
        str = str.replace("[", "");
        str = str.replace("]", "");
        String[] aryId = str.split(",");
        Long[] lAryId = new Long[aryId.length];
        for (int i = 0; i < aryId.length; i++) {
            lAryId[i] = Long.parseLong(aryId[i]);
        }
        return lAryId;
    }


    /**
     * string转map
     *
     * @param param
     * @return
     */
    public static Object getMapValue(String param) {
        Map<String, Object> map = new HashMap<>();
        String str = "";
        String key = "";
        Object value = "";
        char[] charList = param.toCharArray();
        boolean valueBegin = false;
        for (int i = 0; i < charList.length; i++) {
            char c = charList[i];
            if (c == '{') {
                if (valueBegin == true) {
                    value = getMapValue(param.substring(i, param.length()));
                    i = param.indexOf('}', i) + 1;
                    map.put(key, value);
                }
            } else if (c == '=') {
                valueBegin = true;
                key = str;
                str = "";
            } else if (c == ',') {
                valueBegin = false;
                value = str;
                str = "";
                map.put(key, value);
            } else if (c == '}') {
                if (str != "") {
                    value = str;
                }
                map.put(key, value);
                return map;
            } else if (c != ' ') {
                str += c;
            }
        }
        return map;
    }

    /**
     * 值为List转为以逗号隔开并且以单引号括起来的字符串
     *
     * @param listMap
     * @return
     */
    public static Map<String, String> getMapStringByMapList(Map<String, Set<String>> listMap) {
        Map<String, String> map = new HashMap<String, String>();
        for (String key : listMap.keySet()) {
            Set<String> list = listMap.get(key);
            if (list == null) continue;
            String valueString = convertListToSingleQuotesString(list);
            if (StringUtil.isNotEmpty(valueString)) {
                map.put(key, valueString);
            }
        }
        return map;
    }

    /**
     * List转成以单引号括起来字符串
     *
     * @param set
     * @return
     */
    public static String convertListToSingleQuotesString(Set<String> set) {
        if (set == null) return "";
        String ids = "";
        for (String value : set) {
            ids = ids + "\'" + value + "\',";
        }
        ids = ids.equals("") ? "" : ids.substring(0, ids.length() - 1);
        return ids;
    }

    public static boolean equals(String st1, String st2) {
        if (BeanUtils.isEmpty(st1) && BeanUtils.isEmpty(st2)) {
            return true;
        }
        if (BeanUtils.isNotEmpty(st1) && BeanUtils.isNotEmpty(st1)) {
            return st1.equals(st2);
        }
        return false;
    }

    public static boolean LargeThen(String st1, String st2) {
        if (BeanUtils.isNotEmpty(st1) && BeanUtils.isNotEmpty(st1)) {
            return st1.compareTo(st2) > 0;
        }
        return false;
    }

    public static boolean littleThen(String st1, String st2) {
        if (BeanUtils.isNotEmpty(st1) && BeanUtils.isNotEmpty(st1)) {
            return st1.compareTo(st2) < 0;
        }
        return false;
    }

    public static boolean contains(String st1, String st2) {
        if (BeanUtils.isNotEmpty(st1) && BeanUtils.isNotEmpty(st1)) {
            return st1.contains(st2);
        }
        return false;
    }

    public static boolean isStringBelongTo(String target, String boundary) {
        if (BeanUtils.isEmpty(target) || BeanUtils.isEmpty(boundary)) {
            return false;
        }
        String[] boundaryArr = boundary.split(",");
        if (boundaryArr.length <= 0) {
            return false;
        }
        List<String> list = Arrays.asList(boundaryArr);
        return list.contains(target);
    }

    /**
     * <pre>
     * 对字符串进行脱敏处理
     *  System.out.println(StringUtil.wordMask("123456789", 0, 1, "*")); *23456789
     * 	System.out.println(StringUtil.wordMask("123456789", 1, 1, "*")); *23456789
     * 	System.out.println(StringUtil.wordMask("123456789", 0, 2, "*")); **3456789
     * 	System.out.println(StringUtil.wordMask("123456789", 1, 2, "*")); **3456789
     * </pre>
     *
     * @param word        被脱敏的字符
     * @param startLength 被保留的开始长度 前余n位
     * @param endLength   被保留的结束长度 后余n位
     * @param pad         填充字符
     */
    public static String wordMask(String word, int startLength, int endLength, String pad) {
        Assert.isTrue(startLength >= 0, "开始位置必须大于等于0");
        Assert.isTrue(endLength >= 0, "开始位置必须大于等于0");
        Assert.isTrue(startLength <= endLength, "开始位置必须小于等于结束位置");
        if (isEmpty(word)) {
            return word;
        }
        if (endLength > word.length()) {
            endLength = word.length();
        }
        if (startLength > endLength) {
            return word;
        }
        if (startLength > 0) {
            startLength = startLength - 1;
        }
        String startStr = word.substring(0, startLength);

        String endStr = word.substring(endLength, word.length());

        return startStr + StringUtils.leftPad("", endLength - startLength, pad) + endStr;

    }

    /**
     * 检验手机号
     *
     * @param mobile
     * @return
     */
    public static boolean isMobile(String mobile) {
        mobile = String.valueOf(mobile).trim();
        Pattern regex = Pattern.compile("^((1[3-9]{1}))\\d{9}$");
        Matcher matcher = regex.matcher(mobile);
        boolean isMatched = matcher.matches();
        return isMatched;
    }

    /**
     * 检查email是否是邮箱格式，返回true表示是，反之为否
     *
     * @param email
     * @return
     */
    public static boolean isEmail(String email) {
        email = String.valueOf(email).trim();
        Pattern regex = Pattern.compile("\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*");
        Matcher matcher = regex.matcher(email);
        boolean isMatched = matcher.matches();
        return isMatched;
    }

    /**
     * 格式化double为字符串，不丢失精度
     *
     * @param value
     * @return
     */
    public static String format(double value) {
        String dstr = String.valueOf(value);
        String earr[] = dstr.split("E");
        if (earr.length == 2) {
            int e = Integer.valueOf(earr[1]);
            String dotArr[] = earr[0].split("[.]");
            int precision = dotArr[1].length() - e;
            dstr = new BigDecimal(value).setScale(precision, RoundingMode.HALF_EVEN).toPlainString();
        } else if (value % 1 == 0) {
            dstr = String.valueOf(Double.valueOf(value).intValue());
        }
        return dstr;
    }

    /**
     * 判断字符串中是否包含emoji表情
     *
     * @param content
     * @return
     */
    public static boolean hasEmoji(String content) {
        Pattern pattern = Pattern.compile("(?:[\uD83C\uDF00-\uD83D\uDDFF]|[\uD83E\uDD00-\uD83E\uDDFF]|[\uD83D\uDE00-\uD83D\uDE4F]|[\uD83D\uDE80-\uD83D\uDEFF]|[\u2600-\u26FF]\uFE0F?|[\u2700-\u27BF]\uFE0F?|\u24C2\uFE0F?|[\uD83C\uDDE6-\uD83C\uDDFF]{1,2}|[\uD83C\uDD70\uD83C\uDD71\uD83C\uDD7E\uD83C\uDD7F\uD83C\uDD8E\uD83C\uDD91-\uD83C\uDD9A]\uFE0F?|[\u0023\u002A\u0030-\u0039]\uFE0F?\u20E3|[\u2194-\u2199\u21A9-\u21AA]\uFE0F?|[\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55]\uFE0F?|[\u2934\u2935]\uFE0F?|[\u3030\u303D]\uFE0F?|[\u3297\u3299]\uFE0F?|[\uD83C\uDE01\uD83C\uDE02\uD83C\uDE1A\uD83C\uDE2F\uD83C\uDE32-\uD83C\uDE3A\uD83C\uDE50\uD83C\uDE51]\uFE0F?|[\u203C\u2049]\uFE0F?|[\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE]\uFE0F?|[\u00A9\u00AE]\uFE0F?|[\u2122\u2139]\uFE0F?|\uD83C\uDC04\uFE0F?|\uD83C\uDCCF\uFE0F?|[\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA]\uFE0F?)");
        Matcher matcher = pattern.matcher(content);
        return matcher.find();
    }

    public static void main(String[] args) {
        System.out.println(StringUtil.wordMask("123456789", 0, 1, "*"));
        System.out.println(StringUtil.wordMask("123456789", 9, 15, "*"));

        System.out.println(StringUtil.wordMask("123456789", 0, 2, "*"));
        System.out.println(StringUtil.wordMask("123456789", 1, 2, "*"));
    }

    /**
     * 根据规则模版获取标题。
     *
     * <pre>
     * 示例：
     * String rule="{depart:某个部门}申请{时间}公司{活动}";
     * Map<String,String> map=new HashMap<String,String>();
     * map.put("depart","测试部");
     * map.put("时间","周末");
     * map.put("活动","踏青");
     * String subject=BpmUtil.getTitleByRule(rule,map);
     * 返回:
     * 测试部申请周末公司踏青
     * </pre>
     *
     * @param titleRule 主题规则
     * @param map       变量map，用于替换规则中的变量。
     * @return String
     */
    public static String getStrByRule(String titleRule, Map<String, Object> map) {
        if (StringUtils.isEmpty(titleRule))
            return "";
        Pattern regex = Pattern.compile("\\{(.*?)\\}", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
        Matcher matcher = regex.matcher(titleRule);
        while (matcher.find()) {
            String tag = matcher.group(0);
            String rule = matcher.group(1);
            String[] aryRule = rule.split(":");
            String name = "";
            if (aryRule.length == 1) {
                name = rule;
            } else {
                name = aryRule[1];
            }
            if (map.containsKey(name)) {
                Object obj = map.get(name);
                if (obj != null) {
                    try {
                        titleRule = titleRule.replace(tag, obj.toString());
                    } catch (Exception e) {
                        titleRule = titleRule.replace(tag, "");
                    }
                } else {
                    titleRule = titleRule.replace(tag, "");
                }
            } else {
                //使用Groovy脚本引擎先解析
                String defaultValue = "";
                try {
                    if (aryRule.length > 1) {
                        GroovyScriptEngine scriptEngine = AppUtil.getBean(GroovyScriptEngine.class);
                        String script = rule.replace(aryRule[0] + ":", "");
                        defaultValue = scriptEngine.executeString(script, map);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                titleRule = titleRule.replace(tag, defaultValue);
            }
        }
        return titleRule;
    }

    public static String addSpace(Integer num) {
        StringBuffer sb = new StringBuffer();
        if(null == num) {
            return sb.toString();
        }
        for (int i = 1; i <= num - 1; i++) {
            sb.append(" ");
        }
        return sb.toString();
    }

}
