content: /**
   * Copyright &copy; 2012-2016 <a href="https://github.com/HuangBingGui/jeespring">jeespring</a> All rights reserved.
   */
  package com.jeespring.common.utils;
  
  import java.io.UnsupportedEncodingException;
  import java.util.List;
  import java.util.Locale;
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;
  
  import javax.servlet.http.HttpServletRequest;
  
  import org.apache.commons.lang3.BooleanUtils;
  import org.apache.commons.lang3.StringEscapeUtils;
  import org.apache.commons.lang3.text.StrBuilder;
  import org.springframework.web.context.request.RequestContextHolder;
  import org.springframework.web.context.request.ServletRequestAttributes;
  import org.springframework.web.servlet.LocaleResolver;
  
  import com.google.common.collect.Lists;
  
  /**
   * 字符串工具类, 继承org.apache.commons.lang3.StringUtils类
   * @author 黄炳桂 516821420@qq.com
   * @version 2013-05-22
   */
  public class StringUtils extends org.apache.commons.lang3.StringUtils {
  	
      private static final char SEPARATOR = '_';
      private static final String CHARSET_NAME = "UTF-8";
  	/** 空字符串 */
  	private static final String NULLSTR = "";
  
      /**
       * 转换为字节数组
       * @param str
       * @return
       */
      public static byte[] getBytes(String str){
      	if (str != null){
      		try {
  				return str.getBytes(CHARSET_NAME);
  			} catch (UnsupportedEncodingException e) {
  				return null;
  			}
      	}else{
      		return null;
      	}
      }
      
      /**
  	 * 转换为Boolean类型
  	 * 'true', 'on', 'y', 't', 'yes' or '1' (case insensitive) will return true. Otherwise, false is returned.
  	 */
  	public static Boolean toBoolean(final Object val){
  		if (val == null){
  			return false;
  		}
  		return BooleanUtils.toBoolean(val.toString()) || "1".equals(val.toString());
  	}
  	
      /**
       * 转换为字节数组
       * @param str
       * @return
       */
      public static String toString(byte[] bytes){
      	try {
  			return new String(bytes, CHARSET_NAME);
  		} catch (UnsupportedEncodingException e) {
  			return EMPTY;
  		}
      }
      
      /**
  	 * 如果对象为空，则使用defaultVal值 
  	 * 	see: ObjectUtils.toString(obj, defaultVal)
  	 * @param obj
  	 * @param defaultVal
  	 * @return
  	 */
      public static String toString(final Object obj, final String defaultVal) {
      	 return obj == null ? defaultVal : obj.toString();
      }
      
      /**
       * 是否包含字符串
       * @param str 验证字符串
       * @param strs 字符串组
       * @return 包含返回true
       */
      public static boolean inString(String str, String... strs){
      	if (str != null){
          	for (String s : strs){
          		if (str.equals(trim(s))){
          			return true;
          		}
          	}
      	}
      	return false;
      }
      
  	/**
  	 * 替换掉HTML标签方法
  	 */
  	public static String replaceHtml(String html) {
  		if (isBlank(html)){
  			return "";
  		}
  		String regEx = "<.+?>";
  		Pattern p = Pattern.compile(regEx);
  		Matcher m = p.matcher(html);
  		String s = m.replaceAll("");
  		return s;
  	}
  	
  	/**
  	 * 替换为手机识别的HTML，去掉样式及属性，保留回车。
  	 * @param html
  	 * @return
  	 */
  	public static String replaceMobileHtml(String html){
  		if (html == null){
  			return "";
  		}
  		return html.replaceAll("<([a-z]+?)\\s+?.*?>", "<$1>");
  	}
  	
  	/**
  	 * 替换为手机识别的HTML，去掉样式及属性，保留回车。
  	 * @param txt
  	 * @return
  	 */
  	public static String toHtml(String txt){
  		if (txt == null){
  			return "";
  		}
  		return replace(replace(Encodes.escapeHtml(txt), "\n", "<br/>"), "\t", "&nbsp; &nbsp; ");
  	}
  
  	/**
  	 * 缩略字符串（不区分中英文字符）
  	 * @param str 目标字符串
  	 * @param length 截取长度
  	 * @return
  	 */
  	public static String abbr(String str, int length) {
  		if (str == null) {
  			return "";
  		}
  		try {
  			StringBuilder sb = new StringBuilder();
  			int currentLength = 0;
  			for (char c : replaceHtml(StringEscapeUtils.unescapeHtml4(str)).toCharArray()) {
  				currentLength += String.valueOf(c).getBytes("GBK").length;
  				if (currentLength <= length - 3) {
  					sb.append(c);
  				} else {
  					sb.append("...");
  					break;
  				}
  			}
  			return sb.toString();
  		} catch (UnsupportedEncodingException e) {
  			e.printStackTrace();
  		}
  		return "";
  	}
  	
  	public static String abbr2(String param, int length) {
  		if (param == null) {
  			return "";
  		}
  		StringBuffer result = new StringBuffer();
  		int n = 0;
  		char temp;
  		boolean isCode = false; // 是不是HTML代码
  		boolean isHTML = false; // 是不是HTML特殊字符,如&nbsp;
  		for (int i = 0; i < param.length(); i++) {
  			temp = param.charAt(i);
  			if (temp == '<') {
  				isCode = true;
  			} else if (temp == '&') {
  				isHTML = true;
  			} else if (temp == '>' && isCode) {
  				n = n - 1;
  				isCode = false;
  			} else if (temp == ';' && isHTML) {
  				isHTML = false;
  			}
  			try {
  				if (!isCode && !isHTML) {
  					n += String.valueOf(temp).getBytes("GBK").length;
  				}
  			} catch (UnsupportedEncodingException e) {
  				e.printStackTrace();
  			}
  
  			if (n <= length - 3) {
  				result.append(temp);
  			} else {
  				result.append("...");
  				break;
  			}
  		}
  		// 取出截取字符串中的HTML标记
  		String temp_result = result.toString().replaceAll("(>)[^<>]*(<?)",
  				"$1$2");
  		// 去掉不需要结素标记的HTML标记
  		temp_result = temp_result
  				.replaceAll(
  						"</?(AREA|BASE|BASEFONT|BODY|BR|COL|COLGROUP|DD|DT|FRAME|HEAD|HR|HTML|IMG|INPUT|ISINDEX|LI|LINK|META|OPTION|P|PARAM|TBODY|TD|TFOOT|TH|THEAD|TR|area|base|basefont|body|br|col|colgroup|dd|dt|frame|head|hr|html|img|input|isindex|li|link|meta|option|p|param|tbody|td|tfoot|th|thead|tr)[^<>]*/?>",
  						"");
  		// 去掉成对的HTML标记
  		temp_result = temp_result.replaceAll("<([a-zA-Z]+)[^<>]*>(.*?)</\\1>",
  				"$2");
  		// 用正则表达式取出标记
  		Pattern p = Pattern.compile("<([a-zA-Z]+)[^<>]*>");
  		Matcher m = p.matcher(temp_result);
  		List<String> endHTML = Lists.newArrayList();
  		while (m.find()) {
  			endHTML.add(m.group(1));
  		}
  		// 补全不成对的HTML标记
  		for (int i = endHTML.size() - 1; i >= 0; i--) {
  			result.append("</");
  			result.append(endHTML.get(i));
  			result.append(">");
  		}
  		return result.toString();
  	}
  	
  	/**
  	 * 转换为Double类型
  	 */
  	public static Double toDouble(Object val){
  		if (val == null){
  			return 0D;
  		}
  		try {
  			return Double.valueOf(trim(val.toString()));
  		} catch (Exception e) {
  			return 0D;
  		}
  	}
  
  	/**
  	 * 转换为Float类型
  	 */
  	public static Float toFloat(Object val){
  		return toDouble(val).floatValue();
  	}
  
  	/**
  	 * 转换为Long类型
  	 */
  	public static Long toLong(Object val){
  		return toDouble(val).longValue();
  	}
  
  	/**
  	 * 转换为Integer类型
  	 */
  	public static Integer toInteger(Object val){
  		return toLong(val).intValue();
  	}
  	
  	/**
  	 * 获得i18n字符串
  	 */
  	public static String getMessage(String code, Object[] args) {
  		LocaleResolver localLocaleResolver = (LocaleResolver) SpringContextHolder.getBean(LocaleResolver.class);
  		HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();  
  		Locale localLocale = localLocaleResolver.resolveLocale(request);
  		return SpringContextHolder.getApplicationContext().getMessage(code, args, localLocale);
  	}
  	
  	/**
  	 * 获得用户远程地址
  	 */
  	public static String getRemoteAddr(HttpServletRequest request){
  		String remoteAddr = request.getHeader("X-Real-IP");
          if (isNotBlank(remoteAddr)) {
          	remoteAddr = request.getHeader("X-Forwarded-For");
          }else if (isNotBlank(remoteAddr)) {
          	remoteAddr = request.getHeader("Proxy-Client-IP");
          }else if (isNotBlank(remoteAddr)) {
          	remoteAddr = request.getHeader("WL-Proxy-Client-IP");
          }
          return remoteAddr != null ? remoteAddr : request.getRemoteAddr();
  	}
  
  	/**
  	 * 驼峰命名法工具
  	 * @return
  	 * 		toCamelCase("hello_world") == "helloWorld" 
  	 * 		toCapitalizeCamelCase("hello_world") == "HelloWorld"
  	 * 		toUnderScoreCase("helloWorld") = "hello_world"
  	 */
      public static String toCamelCase(String s) {
          if (s == null) {
              return null;
          }
  
          s = s.toLowerCase();
  
          StringBuilder sb = new StringBuilder(s.length());
          boolean upperCase = false;
          for (int i = 0; i < s.length(); i++) {
              char c = s.charAt(i);
  
              if (c == SEPARATOR) {
                  upperCase = true;
              } else if (upperCase) {
                  sb.append(Character.toUpperCase(c));
                  upperCase = false;
              } else {
                  sb.append(c);
              }
          }
  
          return sb.toString();
      }
  
      /**
  	 * 驼峰命名法工具
  	 * @return
  	 * 		toCamelCase("hello_world") == "helloWorld" 
  	 * 		toCapitalizeCamelCase("hello_world") == "HelloWorld"
  	 * 		toUnderScoreCase("helloWorld") = "hello_world"
  	 */
      public static String toCapitalizeCamelCase(String s) {
          if (s == null) {
              return null;
          }
          s = toCamelCase(s);
          return s.substring(0, 1).toUpperCase() + s.substring(1);
      }
  
      /**
       * 转换为JS获取对象值，生成三目运算返回结果
       * @param objectString 对象串
       *   例如：row.user.id
       *   返回：!row?'':!row.user?'':!row.user.id?'':row.user.id
       */
      public static String jsGetVal(String objectString){
      	StringBuilder result = new StringBuilder();
      	StringBuilder val = new StringBuilder();
      	String[] vals = split(objectString, ".");
      	for (int i=0; i<vals.length; i++){
      		val.append("." + vals[i]);
      		result.append("!"+(val.substring(1))+"?'':");
      	}
      	result.append(val.substring(1));
      	return result.toString();
      }
  
  	/**
  	 * * 判断一个字符串是否为空串
  	 *
  	 * @param str String
  	 * @return true：为空 false：非空
  	 */
  	public static boolean isEmpty(String str)
  	{
  		return isNull(str) || NULLSTR.equals(str.trim());
  	}
  
  	/**
  	 * * 判断一个字符串是否为非空串
  	 *
  	 * @param str String
  	 * @return true：非空串 false：空串
  	 */
  	public static boolean isNotEmpty(String str)
  	{
  		return !isEmpty(str);
  	}
  
  	/**
  	 * * 判断一个对象是否为空
  	 *
  	 * @param object Object
  	 * @return true：为空 false：非空
  	 */
  	public static boolean isNull(Object object)
  	{
  		return object == null;
  	}
  
  	/**
  	 * * 判断一个对象是否非空
  	 *
  	 * @param object Object
  	 * @return true：非空 false：空
  	 */
  	public static boolean isNotNull(Object object)
  	{
  		return !isNull(object);
  	}
  
  	/**
  	 * 去空格
  	 */
  	public static String trim(String str)
  	{
  		return (str == null ? "" : str.trim());
  	}
  
  	/**
  	 * 截取字符串
  	 *
  	 * @param str 字符串
  	 * @param start 开始
  	 * @return 结果
  	 */
  	public static String substring(final String str, int start)
  	{
  		if (str == null)
  		{
  			return NULLSTR;
  		}
  
  		if (start < 0)
  		{
  			start = str.length() + start;
  		}
  
  		if (start < 0)
  		{
  			start = 0;
  		}
  		if (start > str.length())
  		{
  			return NULLSTR;
  		}
  
  		return str.substring(start);
  	}
  
  	/**
  	 * 截取字符串
  	 *
  	 * @param str 字符串
  	 * @param start 开始
  	 * @param end 结束
  	 * @return 结果
  	 */
  	public static String substring(final String str, int start, int end)
  	{
  		if (str == null)
  		{
  			return NULLSTR;
  		}
  
  		if (end < 0)
  		{
  			end = str.length() + end;
  		}
  		if (start < 0)
  		{
  			start = str.length() + start;
  		}
  
  		if (end > str.length())
  		{
  			end = str.length();
  		}
  
  		if (start > end)
  		{
  			return NULLSTR;
  		}
  
  		if (start < 0)
  		{
  			start = 0;
  		}
  		if (end < 0)
  		{
  			end = 0;
  		}
  
  		return str.substring(start, end);
  	}
  
  	/**
  	 * * 判断一个对象数组是否为空
  	 *
  	 * @param objects 要判断的对象数组
  	 ** @return true：为空 false：非空
  	 */
  	public static boolean isEmpty(Object[] objects)
  	{
  		return isNull(objects) || (objects.length == 0);
  	}
  
  	/**
  	 * 格式化文本, {} 表示占位符<br>
  	 * 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
  	 * 如果想输出 {} 使用 \\转义 { 即可，如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
  	 * 例：<br>
  	 * 通常使用：format("this is {} for {}", "a", "b") -> this is a for b<br>
  	 * 转义{}： format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
  	 * 转义\： format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
  	 *
  	 * @param template 文本模板，被替换的部分用 {} 表示
  	 * @param params 参数值
  	 * @return 格式化后的文本
  	 */
  	public static String format(String template, Object... params)
  	{
  		if (isEmpty(params) || isEmpty(template))
  		{
  			return template;
  		}
  		return StrFormatter.format(template, params);
  	}
  
  	/**
  	 * 驼峰首字符小写
  	 */
  	public static String uncapitalize(String str)
  	{
  		int strLen;
  		if (str == null || (strLen = str.length()) == 0)
  		{
  			return str;
  		}
  		return new StrBuilder(strLen).append(Character.toLowerCase(str.charAt(0))).append(str.substring(1)).toString();
  	}
  
  	/**
  	 * 下划线转驼峰命名
  	 */
  	public static String toUnderScoreCase(String s)
  	{
  		if (s == null)
  		{
  			return null;
  		}
  		StringBuilder sb = new StringBuilder();
  		boolean upperCase = false;
  		for (int i = 0; i < s.length(); i++)
  		{
  			char c = s.charAt(i);
  
  			boolean nextUpperCase = true;
  
  			if (i < (s.length() - 1))
  			{
  				nextUpperCase = Character.isUpperCase(s.charAt(i + 1));
  			}
  
  			if ((i > 0) && Character.isUpperCase(c))
  			{
  				if (!upperCase || !nextUpperCase)
  				{
  					sb.append(SEPARATOR);
  				}
  				upperCase = true;
  			}
  			else
  			{
  				upperCase = false;
  			}
  
  			sb.append(Character.toLowerCase(c));
  		}
  
  		return sb.toString();
  	}
  
  	/**
  	 * 是否包含字符串
  	 *
  	 * @param str 验证字符串
  	 * @param strs 字符串组
  	 * @return 包含返回true
  	 */
  	public static boolean inStringIgnoreCase(String str, String... strs)
  	{
  		if (str != null && strs != null)
  		{
  			for (String s : strs)
  			{
  				if (str.equalsIgnoreCase(trim(s)))
  				{
  					return true;
  				}
  			}
  		}
  		return false;
  	}
  
  	/**
  	 * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空，则返回空字符串。 例如：HELLO_WORLD->HelloWorld
  	 *
  	 * @param name 转换前的下划线大写方式命名的字符串
  	 * @return 转换后的驼峰式命名的字符串
  	 */
  	public static String convertToCamelCase(String name)
  	{
  		StringBuilder result = new StringBuilder();
  		// 快速检查
  		if (name == null || name.isEmpty())
  		{
  			// 没必要转换
  			return "";
  		}
  		else if (!name.contains("_"))
  		{
  			// 不含下划线，仅将首字母大写
  			return name.substring(0, 1).toUpperCase() + name.substring(1);
  		}
  		// 用下划线将原始字符串分割
  		String[] camels = name.split("_");
  		for (String camel : camels)
  		{
  			// 跳过原始字符串中开头、结尾的下换线或双重下划线
  			if (camel.isEmpty())
  			{
  				continue;
  			}
  			// 首字母大写
  			result.append(camel.substring(0, 1).toUpperCase());
  			result.append(camel.substring(1).toLowerCase());
  		}
  		return result.toString();
  	}
  }
  