java Util

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.qihangedu.tms.annotation.TMSProperty;
import com.qihangedu.tms.common.web.TMSMessageException;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.hibernate.service.spi.ServiceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.lang.reflect.*;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;


@Service
public class Util {
    private static Logger logger = LoggerFactory.getLogger(TMSUtil.class);

    public static final long DEFAULT_SCALE = 100000000L;


    public static final SimpleDateFormat DATA_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
    public static final SimpleDateFormat DATA_TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 字符串类型(YYYY-MM-DD,YYYY/MM/DD)转换成 DATE 类型
     * 新增对英文日期格式支持,如: Wed Oct 10 00:00:00 CST 2012 (excel数据导入运用)
     *
     * @param dateString YYYY-MM-DD,YYYY/MM/DD格式
     * @return date对象
     */
    public static synchronized Date string2Date(String dateString){
        return string2Date(dateString, null);
    }

    public static synchronized Date string2Date(String dateString, String defaultString){
        if(StringUtils.isBlank(defaultString) && StringUtils.isBlank(dateString)){
            return null;
        }

        String ds = dateString;
        if (StringUtils.isBlank(dateString)) {
            ds = defaultString;
        }
        Date date = null;
        try {
            date = DateUtils.parseDate(ds, "yyyy-MM-dd","yyyy/MM/dd");
        } catch (ParseException e) {
            try {
               date = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.US).parse(ds);
            }catch (Exception e1) {
                logger.warn("转化日期格式错误: {}, format:yyyy-MM-dd 或 yyyy/MM/dd", ds);
            }
        }
        return date;
    }


    /**
     * 格式化日期
     * @param date
     * @return
     */
    public static String formatDate(Date date) {
        if (date == null) {
            return "";
        }
        return DATA_FORMAT.format(date);
    }


    /**
     * 格式化时间
     * @param date
     * @return
     */
    public static String formatDateTime(Date date) {
        if (date == null) {
            return "";
        }
        return DATA_TIME_FORMAT.format(date);
    }



    /**
     * 将数字按缺省ModelEntity.SCORE_SCALE的倍数进行放大,用于内部保存.
     * @param srcNumber 需要放大的输入源,字符串类型,可以携带小数
     * @return 放大后的数字,长整型.
     */
    public static synchronized long numberZoomIn(String srcNumber) {
        return srcNumber == null ? 0 : numberZoomIn(srcNumber, DEFAULT_SCALE);
    }

    /**
     * 将数字按照传入的倍数进行放大,用于内部保存.
     * @param srcNumber 需要放大的输入源,字符串类型,可以携带小数
     * @param scale 放大的倍数
     * @return 放大后的数字,长整型.
     */
    public static synchronized long numberZoomIn(String srcNumber, long scale) {
        double srcDouble = NumberUtils.toDouble(srcNumber, 0);
        BigDecimal bigDecimal = new BigDecimal(srcDouble * 10000).multiply(new BigDecimal(scale)).divide(new BigDecimal(10000));
        String string=bigDecimal.toString();
        if(bigDecimal.toString().indexOf(".")>0){
            //防止 越界
            string=bigDecimal.toString().substring(0,bigDecimal.toString().indexOf("."));
        }
        long result = Long.valueOf(string);
        if(logger.isDebugEnabled()) {
            logger.debug("scale {}*{} is from {} to {}", srcNumber, scale, srcDouble, result);
        }
        return result;
    }

    /**
     * 将数值转换为百分比
     *
     * @param value
     * @return
     */
    public static String digitalToPercent(String value){
        try {
            if(StringUtils.isBlank(value)){
                return null;
            }

            if(StringUtils.indexOf(value, "%") != -1){
                return value;
            }
            BigDecimal bigDecimal = new BigDecimal(value).multiply(new BigDecimal(100));
            return bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP) + "%";
        }catch (Exception e){
            logger.error(e.getMessage(), e);
        }
        return value;
    }

    /**
     * 将百分比转换为数值
     *
     * @param value
     * @return
     */
    public static String percentToDigital(String value){
        try {
            if(StringUtils.isBlank(value)){
                return null;
            }
            if(!StringUtils.endsWith(value, "%")){
                return value;
            }else{
                value = value.replace("%", "");
            }
            BigDecimal bigDecimal = new BigDecimal(value).divide(new BigDecimal(100));
            return bigDecimal.toPlainString();
        }catch (Exception e){
            logger.error(e.getMessage(), e);
        }
        return value;
    }

    public static void main(String[] args) {
        numberZoomIn("76.6",100000000);
    }


//    /**
//     * 根据小数点保留位数,计算出需要保存的整型。小数点以外的数字就不需要了。
//     * @param srcStringDigital 字符串形式的源数据,可能是整型,可能是浮点,若是null表示为0
//     * @return 扩大了小数点保留位后的整型
//     */
//    public static synchronized int scaleFromDoubleToInt(String srcStringDigital) {
//        return scaleFromDoubleToInt(srcStringDigital, 8);
//    }
//
//    public static synchronized int scaleFromDoubleToInt(String srcStringDigital, int digitalPlace) {
//        double sourceDouble = NumberUtils.toDouble(srcStringDigital);
//        return scaleFromDoubleToInt(sourceDouble, digitalPlace);
//
//    }
//
//    /**
//     * 根据小数点保留位数,计算出需要保存的整型。小数点以外的数字就不需要了。
//     * @param srcDouble double类型的源数据
//     * @param digitalPlace 小数点保留位数,0即不保留,直接取整
//     * @return 扩大了小数点保留位后的整型
//     */
//    public static synchronized int scaleFromDoubleToInt(double srcDouble, int digitalPlace) {
//        int result = (int) (srcDouble * Math.pow(10, digitalPlace));
//        logger.debug("Math.pow(10, 8) = {}", Math.pow(10, digitalPlace));
//        logger.debug("convert {} with digital place {}, result is {}", srcDouble, digitalPlace, result);
//        return result;
//    }
//
//    /**
//     * 将整形缩小小数点位数后返回字符串
//     * @param srcValue 整型,数据源
//     * @param digitalPlace 需要缩小的小数点位数
//     * @param isTrimZero 是否裁剪掉末尾的不用的0
//     * @return 格式化输出的字符串
//     */
//    public static synchronized String scaleFromLongToString(long srcValue, int digitalPlace, boolean isTrimZero){
//    	if(srcValue == 0L){
//    		return "0";
//    	}
//
//        BigDecimal bd = new BigDecimal(srcValue);
////        bd = bd.setScale(digitalPlace);
//        bd = bd.movePointLeft(digitalPlace);
//
//        if(isTrimZero){
//            return subZeroAndDot(bd.toString());
//        }
//        else{
//            return bd.toString();
//        }
//
//    }

//    /**
//     * 将整形缩小小数点位数后返回字符串
//     * @param srcValue 整型,数据源
//     * @param digitalPlace 需要缩小的小数点位数
//     * @param isTrimZero 是否裁剪掉末尾的不用的0
//     * @return 格式化输出的字符串
//     */

    /**
     * 将内部保存的数字(长整型)缩小或扩大ModelEntity.SCORE_SCALE倍后返回字符串
     * @param srcLong 长整型,数据源
     * @return 格式化输出的字符串,小数点后面不再带"0"
     */
    public static synchronized String numberZoomOutAndToString(long srcLong) {
        return numberZoomOutAndToString(srcLong, DEFAULT_SCALE);
    }

    /**
     * 将内部保存的数字(长整型)缩小或扩大多少倍后返回字符串
     * @param srcLong 长整型,数据源
     * @param scale 需要缩小或扩大的倍数
     * @return 格式化输出的字符串,小数点后面不再带"0"
     */
    public static synchronized String numberZoomOutAndToString(long srcLong, long scale) {
        BigDecimal bdLong = new BigDecimal(srcLong);
        BigDecimal bdScale = new BigDecimal(scale);
        BigDecimal result = bdLong.divide(bdScale, 2, BigDecimal.ROUND_HALF_UP);

        String str = subZeroAndDot(result.toString());

//        if(logger.isDebugEnabled()) {
//            logger.debug("input {} scale {} and result is {} to String is {}", srcLong, scale, result, str);
//        }

        return str;
    }

    /**
     * 使用java正则表达式去掉多余的.与0
     * <code>
     Float f = 1f;
     System.out.println(f.toString());//1.0
     System.out.println(subZeroAndDot("1"));;  // 转换后为1
     System.out.println(subZeroAndDot("10"));;  // 转换后为10
     System.out.println(subZeroAndDot("1.0"));;  // 转换后为1
     System.out.println(subZeroAndDot("1.010"));;  // 转换后为1.01
     System.out.println(subZeroAndDot("1.01"));;  // 转换后为1.01
     </code>
     * @param s 数字字符串
     * @return 不带0和小数点(若是最后一位)
     */
    public static synchronized String subZeroAndDot(String s) {
        if (s.indexOf(".") > 0) {
            s = s.replaceAll("0+?$", "");//去掉多余的0
            s = s.replaceAll("[.]$", "");//如最后一位是.则去掉
        }
        return s;
    }
    
    /**
	 * 字符串,拼装list  例"a,b,c"转换为list
	 * @param info 字符串
	 * @param regex 分隔符
	 * @return list
	 */
	public static synchronized List<String> str2List(String info, String regex) {
		List<String> lst = new ArrayList<String>();
		if (info != null) {
			String infoArr[] = info.split(regex);
			for (String str : infoArr) {
				if (StringUtils.isNotBlank(str)) {
					lst.add(str);
				}
			}
		}
		return lst;
	}

    /**
     * 获得两个日期之间的年份差额。
     *
     * 满12个月的为1年,不足12个月的为0年。规则调整为:取年份的差值,并向上进位(不
     * 满一年的算一年)。
     * @param startDate 开始日期
     * @param currentDate 当前日期
     * @return 差额年份,不足一年的为0.
     */
    public static synchronized int getYearsOfAge(Date startDate, Date currentDate) {
        Calendar startCal = Calendar.getInstance();
        startCal.setTime(startDate);

        Calendar currentCal = Calendar.getInstance();
        currentCal.setTime(currentDate);

//        int startMonths = startCal.get(Calendar.YEAR) * 12 + startCal.get(Calendar.MONTH);
//        int currentMonths = currentCal.get(Calendar.YEAR) * 12 + currentCal.get(Calendar.MONTH);
//
//        int months = currentMonths - startMonths;
//
//        return months / 12;
        // 根据启东的工作年限的计算规则,调整为向上取整
        // 2013.12.30~2014.10.1,为两年
        int startYear = startCal.get(Calendar.YEAR);
        int currentYear = currentCal.get(Calendar.YEAR);

        return currentYear - startYear + 1;
    }

    /**
     * 从requst中获取json数据
     *
     * @param request
     * @return json格式数据
     * @throws java.io.IOException
     */
    public static String getJsonBody(HttpServletRequest request) {
        String body = null;
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader bufferedReader = null;
        try {
            InputStream inputStream = request.getInputStream();
            if (inputStream != null) {
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
                char[] charBuffer = new char[128];
                int bytesRead = -1;
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead);
                }
            } else {
                stringBuilder.append("");
            }
        } catch (IOException ex) {
            logger.warn("从request里读取数据流错误", ex.toString());
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException ex) {
                    logger.warn("关闭request读取数据流错误", ex.toString());
                }
            }
        }

        request.setAttribute(REQUEST_BODY, stringBuilder.toString());
        //解决表情符号字符的问题,将他们先都过滤掉。
        //by tanliang
        //2015-10-22
        String str = filterOffUtf8Mb4(stringBuilder.toString());
        return str;
//        try {
//            return new String(stringBuilder.toString().getBytes("gbk"));
//        } catch (UnsupportedEncodingException e) {
//            logger.error(e.getMessage(), e);
//            return "";
//        }
    }


    public static <T> T getJsonBody2Object(HttpServletRequest request, Class<T> clazz){
        String jsonString = getJsonBody(request);
        return JSON.parseObject(jsonString, clazz);
    }

    public static JSONObject getJsonObject(HttpServletRequest request){
        String jsonString = getJsonBody(request);
        return JSON.parseObject(jsonString);
    }

//    private static boolean isEmojiCharacter(char codePoint) {
//        return (codePoint == 0x0) ||
//                (codePoint == 0x9) ||
//                (codePoint == 0xA) ||
//                (codePoint == 0xD) ||
//                ((codePoint >= 0x20) && (codePoint <= 0xD7FF)) ||
//                ((codePoint >= 0xE000) && (codePoint <= 0xFFFD)) ||
//                ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF));
//    }
//
//
//    /**
//     * 检测是否有emoji字符
//     *
//     * @param source
//     * @return 一旦含有就抛出
//     */
//    public static boolean containsEmoji(String source) {
//        if (StringUtils.isBlank(source)) {
//            return false;
//        }
//
//        int len = source.length();
//        for (int i = 0; i < len; i++) {
//            char codePoint = source.charAt(i);
//            if (isEmojiCharacter(codePoint)) {
//                //do nothing,判断到了这里表明,确认有表情字符
//                return true;
//            }
//        }
//        return false;
//    }
//
//
//    /**
//     * 过滤emoji 或者 其他非文字类型的字符
//     *
//     * @param source
//     * @return
//     */
//    public static String filterEmoji(String source) {
//
//        if (!containsEmoji(source)) {
//            return source;//如果不包含,直接返回
//        }
//        //到这里铁定包含
//        StringBuilder buf = null;
//
//        int len = source.length();
//
//        for (int i = 0; i < len; i++) {
//            char codePoint = source.charAt(i);
//
//            if (isEmojiCharacter(codePoint)) {
//                if (buf == null) {
//                    buf = new StringBuilder(source.length());
//                }
//
//                buf.append(codePoint);
//            } else {
//            }
//        }
//
//        if (buf == null) {
//            return source;//如果没有找到 emoji表情,则返回源字符串
//        } else {
//            if (buf.length() == len) {//这里的意义在于尽可能少的toString,因为会重新生成字符串
//                buf = null;
//                return source;
//            } else {
//                return buf.toString();
//            }
//        }
//    }

    /**
     * 过滤掉超过3个字节的UTF8字符
     * @param text
     * @return
     */
    public static String filterOffUtf8Mb4(String text)  {
        try {
            if(text == null)
                return null;
            byte[] bytes = text.getBytes("utf-8");
            if(!hasOffUtf8Mb4(bytes))
                return text;

            ByteBuffer buffer = ByteBuffer.allocate(bytes.length);
            int i = 0;
            while (i < bytes.length) {
                short b = bytes[i];
                if (b > 0) {
                    buffer.put(bytes[i++]);
                    continue;
                }


                b += 256; // 去掉符号位

                if (((b >> 5) ^ 0x6) == 0) {
                    buffer.put(bytes, i, 2);
                    i += 2;
                } else if (((b >> 4) ^ 0xE) == 0) {
                    buffer.put(bytes, i, 3);
                    i += 3;
                } else if (((b >> 3) ^ 0x1E) == 0) {
                    i += 4;
                } else if (((b >> 2) ^ 0x3E) == 0) {
                    i += 5;
                } else if (((b >> 1) ^ 0x7E) == 0) {
                    i += 6;
                } else {
                    buffer.put(bytes[i++]);
                }
            }
            buffer.flip();
            return new String(buffer.array(), 0, buffer.limit(), "utf-8");
        } catch (UnsupportedEncodingException e) {
            logger.error(e.getMessage(), e);
            return text;
        }
    }

    private static boolean hasOffUtf8Mb4(byte[] bytes) {
        int i = 0;
        while (i < bytes.length) {
            short b = bytes[i];
            if (b > 0) {
                i++;
                continue;
            }


            b += 256; // 去掉符号位

            if (((b >> 5) ^ 0x6) == 0) {
                i += 2;
            } else if (((b >> 4) ^ 0xE) == 0) {
                i += 3;
            } else if (((b >> 3) ^ 0x1E) == 0) {
                return true;
            } else if (((b >> 2) ^ 0x3E) == 0) {
                return true;
            } else if (((b >> 1) ^ 0x7E) == 0) {
                return true;
            } else {
//                buffer.put(bytes[i++]);
                i++;
            }
        }
        return false;
    }

    //首字母转小写
    public static String toLowerCaseFirstOne(String s) {
        if (Character.isLowerCase(s.charAt(0)))
            return s;
        else
            return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
    }

    //首字母转大写
    public static String toUpperCaseFirstOne(String s) {
        if (Character.isUpperCase(s.charAt(0)))
            return s;
        else
            return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();
    }

    /**
     * 判断文件后缀是否合法
     * @param fileName
     * @param suffix
     * @return
     */
    public static boolean isFileSuffix(String fileName, String...suffix){
        for(String suf : suffix){
            if(fileName.endsWith(suf)){
                return true;
            }
        }
        return false;
    }


    /**
     * 将list<Object> 对象转换为map对象.
     *
     * @param objs
     * @param propName 对象属性名称,值对应map中key
     * @return map key --> propName对应属性的值
     *             value --> object
     */
    public static <T> Map<String, T> toMap(final List<T> objs, final String propName){
        Map<String, T> results = new HashMap<>();
        if(objs == null) return results;
        for(T obj : objs){
            try {
                String propObj = PropertyUtils.getProperty(obj, propName) + "";
                results.put(propObj, obj);
            } catch (Exception e) {
                logger.info("未知属性名称,{}", propName);
                throw new ServiceException(e.getMessage());
            }
        }
        return results;
    }

    public static String toString(Collection<? extends Object> objects,String spilt){

        StringBuffer sb = new StringBuffer();

        if (objects != null && objects.size()>0) {
            for (Object object : objects) {
                sb.append(object.toString()+spilt) ;
            }
        }
        return sb.toString();
    }

    //==================================================================================================================
    // 合并方法
    //==================================================================================================================
    public static final int MERGE_FLAG_NORMAL = 0;
    public static final int MERGE_FLAG_ADD_NEW = 1;
    public static final int MERGE_FLAG_REMOVE_OLD = 2;
    public static final int MERGE_FLAG_COMBINE = 3;

    /**
     * 合并对象的属性值。
     *
     * 利用属性上的@TMSProperty(merge=false)注解,则不需要复制该属性上的值。
     * @param currentCollection 需要合并的对象集合
     * @param postCollection 提交数据的对象集合
     * @param flag 0,默认,不允许针对当前集合新增和删除对象;
     *             1,仅新增在当前集合中不存在的对象;对于新增的对象,完全复制,不考虑合并(否则key值也会失效)。
     *             2、仅删除在当前集合中多余的对象;
     *             3、同时可以新增和删除当前集合中的对象。相当于完全依赖postCollection中的对象情况
     * @param <T> 泛型。注:对于对象唯一性的判断,主要依赖T的hashCode()方法。
     */
    public static <T> void mergeCollection(Collection<T> currentCollection, Collection<T> postCollection, int flag) {
//        Map<Integer, T> currentMap = collectionToMap(currentCollection);
//        Map<Integer, T> postMap = collectionToMap(postCollection);
//        mergeCore(currentMap, postMap, flag);
//        currentCollection.clear();
//        currentCollection.addAll(currentMap.values());
        mergeCore(currentCollection, postCollection, flag);
    }


//    /**
//     * 合并对象V上的属性值。K只是索引值。适用于Map<String, EmployeeEntity>,其中key为empId
//     *
//     * 利用属性上的@TMSProperty(merge=false)注解,则不需要复制该属性上的值。
//     * @param currentMap 需要合并的对象集合
//     * @param postMap 提交数据的对象集合
//     * @param flag 0,默认,不允许针对当前集合新增和删除对象;
//     *             1,仅新增在当前集合中不存在的对象;
//     *             2、仅删除在当前集合中多余的对象;
//     *             3、同时可以新增和删除当前集合中的对象。相当于完全依赖postCollection中的对象情况
//     * @param <K> 泛型。注:对于对象唯一性的判断,主要依赖K的hashCode()方法。
//     * @param <V> 泛型。目前暂不支持V为Collection和Map。
//     *
//     */
//    protected <K, V> void mergeMap(Map<K, V> currentMap, Map<K, V> postMap, int flag) {
//    }

//    public static <V> void mergeCore(Map<Integer, V> currentMap, Map<Integer, V> postMap, int flag) {
//        switch (flag) {
//            case MERGE_FLAG_NORMAL:
//                mergeCoreNormal(currentMap, postMap, flag);
//                break;
//            case MERGE_FLAG_ADD_NEW:
//                mergeCoreAdd(currentMap, postMap, flag);
//                break;
//            case MERGE_FLAG_REMOVE_OLD:
//                mergeCoreRemove(currentMap, postMap, flag);
//                break;
//            case MERGE_FLAG_COMBINE:
//                mergeCoreRemove(currentMap, postMap, flag);
//                mergeCoreAdd(currentMap, postMap, flag);
//                break;
//        }
//
//    }

    public static <T> void mergeCore(Collection<T> currentCollection, Collection<T> postCollection, int flag) {
        switch (flag) {
            case MERGE_FLAG_NORMAL:
                mergeCoreNormal(currentCollection, postCollection, flag);
                break;
            case MERGE_FLAG_ADD_NEW:
                mergeCoreAdd(currentCollection, postCollection, flag);
                break;
            case MERGE_FLAG_REMOVE_OLD:
                mergeCoreRemove(currentCollection, postCollection, flag);
                break;
            case MERGE_FLAG_COMBINE:
                mergeCoreRemove(currentCollection, postCollection, flag);
                mergeCoreAdd(currentCollection, postCollection, flag);
                break;
        }

    }

    //内部实现方法
//    protected static <V> void mergeCoreNormal(Map<Integer, V> currentMap, Map<Integer, V> postMap, int flag) {
//        for (Map.Entry<Integer, V> postEntry : postMap.entrySet()) {
//            if (currentMap.containsKey(postEntry.getKey())) {
//                merge(currentMap.get(postEntry.getKey()), postEntry.getValue(), flag);
//            }
//        }
//    }
    protected static <T> void mergeCoreNormal(Collection<T> currentCollection, Collection<T> postCollection, int flag) {
        for (T ct : currentCollection) {
//            if(!isComplexClass(ct)) continue;
            T pt = findT(postCollection, ct);
            if(pt != null && isComplexClass(ct)) {
                merge(ct, pt, flag);
            }
        }
    }

    protected static <T> T findT(Collection<T> collection, T t) {
        for(T ct:collection) {
            if(ct != null && ct.equals(t))
                return ct;
        }
        return null;
    }

    protected static <T> boolean isComplexClass(T t) {
        if(t.getClass().isPrimitive() || t instanceof String || t instanceof Date) {
            logger.warn("can not merge primitive/String/Date class object. Ony replace can do.");
            return false;
        }
        return true;
    }


    //内部实现方法
//    @SuppressWarnings("unchecked")
//    protected static <V> void mergeCoreAdd(Map<Integer, V> currentMap, Map<Integer, V> postMap, int flag) {
//        for (Map.Entry<Integer, V> postEntry : postMap.entrySet()) {
//            if (currentMap.containsKey(postEntry.getKey())) {
//                merge(currentMap.get(postEntry.getKey()), postEntry.getValue(), flag);
//            } else {
//                try {
//                    V v = (V) postEntry.getValue().getClass().newInstance();
//                    //需要复制一下hashCode的值
//                    copyPrimaryKey(v, postEntry.getValue());
//                    merge(v, postEntry.getValue(), flag);
//                    currentMap.put(postEntry.getKey(), v);
//                } catch (InstantiationException | IllegalAccessException e) {
//                    logger.error(e.getMessage(), e);
//                }
//            }
//        }
//    }

    @SuppressWarnings("unchecked")
    protected static <T> void mergeCoreAdd(Collection<T> currentCollection, Collection<T> postCollection, int flag) {
        for(T pt : postCollection) {
//            if(!isComplexClass(pt)) continue;
            T ct = findT(currentCollection, pt);
            if(ct != null && isComplexClass(pt)) {
                merge(ct, pt, flag);
            }
            else if(isComplexClass(pt)){
                try {
                    T t =  (T) pt.getClass().newInstance();
                    //需要复制一下hashCode的值
                    copyPrimaryKey(t, pt);
                    merge(t, pt, flag);
                    currentCollection.add(t);
                } catch (InstantiationException | IllegalAccessException e) {
                    logger.error(e.getMessage(), e);
                }
            }
            else {
                currentCollection.add(pt);
            }
        }
    }

    protected static <T> void copyPrimaryKey(T currentObj, T postObj) {
        if(currentObj == null || postObj == null) {
            return;
        }

        Collection<Field> fields = getAllDeclaredField(postObj.getClass());
        for(Field field : fields) {
            TMSProperty tmsProperty = field.getAnnotation(TMSProperty.class);
            if(tmsProperty!=null && !tmsProperty.isPrimaryKey()) {
                logger.trace("pass {}-{}", field.getDeclaringClass(), field.getName());
                continue;
            }

            try {
                logger.debug("copy {}-{}", field.getDeclaringClass(), field.getName());
                PropertyUtils.setProperty(currentObj, field.getName(), PropertyUtils.getProperty(postObj, field.getName()));
            } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                logger.error(e.getMessage(), e);
            }
        }

    }

    //内部实现方法
    protected static <T> void mergeCoreRemove(Collection<T> currentCollection, Collection<T> postCollection, int flag) {
        Collection<Integer> removeCollection = new ArrayList<>();
        Iterator<T> iterator = currentCollection.iterator();
        while(iterator.hasNext()) {
            T ct = iterator.next();
//            if(!isComplexClass(ct))
//                continue;

            T pt = findT(postCollection, ct);
            if(pt != null && isComplexClass(ct)) {
                merge(ct, pt, flag);
            }
            else {
                iterator.remove();
            }
        }
    }
//    protected static <V> void mergeCoreRemove(Map<Integer, V> currentMap, Map<Integer, V> postMap, int flag) {
//        Collection<Integer> removeCollection = new ArrayList<>();
//        for (Map.Entry<Integer, V> currentEntry : currentMap.entrySet()) {
//            if (postMap.containsKey(currentEntry.getKey())) {
//                merge(currentEntry.getValue(), postMap.get(currentEntry.getKey()), flag);
//            } else {
//                removeCollection.add(currentEntry.getKey());
//            }
//        }
//
//        for(int key : removeCollection) {
//            currentMap.remove(key);
//        }
//    }

    /**
     * 合并对象的属性值。如果属性为集合,则会递归合并。
     *
     * 利用属性上的@TMSProperty(merge=false)注解,则不需要复制该属性上的值。如果这两个对象的hashCode值不一致,则不会进行合并,并且
     * 抛出异常。
     *
     * @param currentObj 需要合并的对象
     * @param postObj 提交数据的对象
     * @param flag 仅针对属性为集合时有效
     *             0,默认,不允许针对当前集合新增和删除对象;
     *             1,仅新增在当前集合中不存在的对象;
     *             2、仅删除在当前集合中多余的对象;
     *             3、同时可以新增和删除当前集合中的对象。相当于完全依赖集合中的对象情况
     * @param <T> 泛型。注:对于对象唯一性的判断,主要依赖T的hashCode()方法。
     */
    @SuppressWarnings("unchecked")
    public static <T> void merge(T currentObj, T postObj, int flag) {
        if(currentObj == null || postObj == null) {
            return;
        }

        if(!currentObj.getClass().equals(postObj.getClass())) {
            return;
        }

        if(currentObj.getClass().isPrimitive() || currentObj instanceof String) {
            return;
        }

        if(currentObj.hashCode() != postObj.hashCode() && !currentObj.equals(postObj)) {
            return;
        }

//        Field fields[] = postObj.getClass().getDeclaredFields();
        Collection<Field> fields = getAllDeclaredField(postObj.getClass());
        for(Field field : fields) {
            //静态的就不复制了,add by tanliang, 2015-12-15
            if(Modifier.isStatic(field.getModifiers()))
                continue;
            TMSProperty tmsProperty = field.getAnnotation(TMSProperty.class);
            if(tmsProperty!=null && !tmsProperty.merge()) {
                logger.trace("pass {}-{}", field.getDeclaringClass(), field.getName());
                continue;
            }

//            //对于field为primary key,只有在新增模式下是需要复制的。否则忽略。
//            if(tmsProperty != null && tmsProperty.isPrimaryKey() ) {
//                if (flag != MERGE_FLAG_ADD_NEW && flag != MERGE_FLAG_COMBINE) {
//                    continue;
//                }
//                logger.debug("is primary key but need copy.");
//            }
            try {
                //assertTrue(Collection.class.isAssignableFrom(List.class));
                if(Collection.class.isAssignableFrom(field.getType())) {
                    //获取集合的泛型类型:
//                    Class cls = getGenericClass(field);
//
//                    if(cls.isPrimitive() || Date.class.isAssignableFrom(cls) || String.class.isAssignableFrom(cls)) {
//                        //如果是简单对象,则直接根据flag进行合并
//
//                        Collection<T> currentCollection = (Collection<T>)PropertyUtils.getProperty(currentObj, field.getName());
//                        Collection<T> postCollection = (Collection<T>)PropertyUtils.getProperty(postObj, field.getName());
//
//                        switch (flag) {
//                            case MERGE_FLAG_NORMAL:
//                                mergeCoreNormal(currentCollection, postCollection, flag);
//                                break;
//                            case MERGE_FLAG_ADD_NEW:
//                                mergeCoreAdd(currentCollection, postCollection, flag);
//                                break;
//                            case MERGE_FLAG_REMOVE_OLD:
//                                mergeCoreRemove(currentCollection, postCollection, flag);
//                                break;
//                            case MERGE_FLAG_COMBINE:
//                                mergeCoreRemove(currentCollection, postCollection, flag);
//                                mergeCoreAdd(currentCollection, postCollection, flag);
//                                break;
//                        }
//                    }
//                    else {
                        //递归
                        mergeCollection((Collection<T>) PropertyUtils.getProperty(currentObj, field.getName()), (Collection<T>) PropertyUtils.getProperty(postObj, field.getName()), flag);
//                    }
                }
//                else if(field.getDeclaringClass().isAssignableFrom(Map.class)) {
//                    //暂不支持递归,直接复制即可。.
//                }
                else {
                    logger.debug("copy {}-{}", field.getDeclaringClass(), field.getName());
                    PropertyUtils.setProperty(currentObj, field.getName(), PropertyUtils.getProperty(postObj, field.getName()));
                }
            } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                logger.error(e.getMessage(), e);
            }
        }
    }


    /**
     * 通用的获取到指定类所有类属性字段的方法,包括继承而来的属性字段。一般Class中的getDeclaredFields()方法是不包括继承属性的。
     * @param clazz 类
     * @return 所有字段对象的集合
     */
    public static Collection<Field> getAllDeclaredField(Class<?> clazz) {
        Class<?> lastClazz = clazz;

        Collection<Field> allFields = new ArrayList<>();
        for (; lastClazz != Object.class; lastClazz = lastClazz.getSuperclass()) {
            Field fields[] = lastClazz.getDeclaredFields();
            for(Field field : fields) {
                if(findField(allFields, field.getName()) == null) {
                    allFields.add(field);
                }
            }
//            CollectionUtils.addAll(fields, lastClazz.getDeclaredFields());
        }

        return allFields;
    }

    //
    private static Field findField(Collection<Field> fields, String name) {
        for(Field field : fields) {
            if(field.getName().equals(name)) {
                return field;
            }
        }
        return null; //没有找到
    }

    /**
     * 简单的将集合对象hashCode后形成map,方便后面定位查找。
     * @param c 对象的集合
     * @param <T> 可被正确hashCode的类
     * @return key为hashCode值,value为对象本身的map。
     */
    public static <T> Map<Integer, T> collectionToMap(Collection<T> c) {
        Map<Integer, T> map = new HashMap<>();
        for(T t : c) {
            map.put(t.hashCode(), t);
        }
        return map;
    }

    public static Class getGenericClass(Field field) {
        if(Collection.class.isAssignableFrom(field.getType())) {
            Type type = field.getGenericType();
            if (type instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType) type;
                //目前只取第一个泛型
                return (Class) parameterizedType.getActualTypeArguments()[0];
            }
        }
        return Object.class;
    }

    /**
     * 合并两个id集合
     * @param managedIds 管理范围的id集合,也就是标准
     * @param queryIds 业务查询出来的id集合,也就是目标
     * @param pageSize 分页的页行数
     * @param pageNo 分页的页码,从1开始
     * @return 如果业务id在管理范围内,就保留下来,最后按分页的要求组合成新的集合。
     */
    public static Collection<String> mergeIds(Collection<String> managedIds, Collection<String> queryIds, int pageSize, int pageNo) {
        long offset = (pageNo - 1) * pageSize;
        long limit = pageNo * pageSize;
        long fetchPoint = 0;

        Collection<String> result = new ArrayList<>(pageSize);
        for(String id : queryIds) {
            if(managedIds != null && !managedIds.contains(id)) {
                continue;
            }

            if(fetchPoint < offset)
                continue;

            if(fetchPoint > limit)
                break;

            result.add(id);
            fetchPoint++;
        }
        return result;
    }




    /**
     * 获取List中第一个元素的Field
     * @param list
     * @param fieldName
     * @param <T>
     * @return
     */
    private static <T> Field getFirstElementField(List<T> list,String fieldName){

        if (list == null || list.isEmpty()) {
            return null;
        }


        Class<? extends Object> clazz = list.get(0).getClass();
        Class<? extends Object> clazz0 = clazz;
        int count = 0;
        while (clazz != Object.class && count < 20) {
            Field field = null;
            try {
                field = clazz.getDeclaredField(fieldName);
            } catch (NoSuchFieldException e) {
            }
            if (field != null) {
                field.setAccessible(true);
                return field;
            }
            clazz = clazz.getSuperclass();
            count++;
        }

        logger.error("{}没有此属性{}", clazz0.getName(), fieldName);

        return null;
    }


    /**
     * 查找或排除集合中的元素,私有方法以供reject和find调用
     * @param list
     * @param fieldName
     * @param fieldValue
     * @param isReject
     * @param <T>
     * @return
     */
    private static <T> List<T> findOrReject(List<T> list,String fieldName,Object fieldValue,boolean isReject){

        Field field = getFirstElementField(list, fieldName);

        if (field == null) {
            return list;
        }


        Set<Object> targets = new HashSet<>();

        if (fieldValue instanceof Collection){
            targets.addAll((Collection)fieldValue);
        }else {
            targets.add(fieldValue);
        }



        List<T> result = new ArrayList<>();

        for (T object : list) {
            try {
                Object value = field.get(object);

                if (isReject) {

                    if(!targets.contains(value)){
                        result.add(object);
                    }

                } else {
                    if(targets.contains(value)){
                        result.add(object);
                    }
                }

            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }

        return result;
    }

    /**
     * 从list中过滤掉指定属性指定值的元素
     * @param list
     * @param fieldName
     * @param fieldValue
     * @param <T>
     * @return
     */
    public static <T> List<T> reject(List<T> list,String fieldName,Object fieldValue){
        return findOrReject(list,fieldName,fieldValue,true);
    }


    /**
     * 从list中过滤掉指定属性指定值的元素
     * @param list
     * @param fieldName
     * @param fieldValue
     * @param <T>
     * @return
     */
    public static <T> Object findOne(List<T> list,String fieldName,Object fieldValue){
        List<T> list2 = findOrReject(list, fieldName, fieldValue, false);
        if (isEmpty(list2)){
            return null;
        }
        return list2.get(0);
    }


    /**
     * 从list中过滤掉指定属性指定值的元素
     * @param list
     * @param fieldName
     * @param fieldValue
     * @param <T>
     * @return
     */
    public static <T> List<T> find(List<T> list,String fieldName,Object fieldValue){
        return findOrReject(list,fieldName,fieldValue,false);
    }


    /**
     * 模仿underscore的pluck函数
     * var stooges = [{name: 'moe', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 60}];
     * _.pluck(stooges, 'name'); => ["moe", "larry", "curly"]
     * @param list
     * @param fieldName
     * @return
     */
    public static <T> List pluck(List<T> list,String fieldName){
        Field field = getFirstElementField(list, fieldName);

        if (field == null) {
            return new ArrayList<>();
        }

        List<Object> result = new ArrayList<>();

        for (T object : list) {
            try {
                Object value = field.get(object);
                if (value != null) {
                    result.add(value);
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return result;
    }


    /**
     * 判断对象是否为空
     * @param object
     * @return
     * @throws TMSMessageException
     */
    public static boolean isEmpty(Object object) {
        if (object == null) {
            return true;
        }

        if (object.getClass().isArray()) {
            Object[] arr = (Object[]) object;
            return arr.length == 0;
        }

        if (object instanceof Map) {
            Map m = (Map) object;
            return m.isEmpty();
        }

        if (object instanceof Collection) {
            Collection c = (Collection) object;
            return c.isEmpty();
        }

        if (object instanceof String) {
            String s = (String) object;
            s = s.trim();
            return s.isEmpty();
        }

        logger.error("只能判断数组,Map,Collection,String");

        return false;
    }


    public static String encodeHtml(String str){
        if (str != null) {
            str = str.replaceAll("<", "<");
            str = str.replaceAll(">", ">");
        }
        return str;
    }


    /**
     * 求两个集合的差集
     * @param list1
     * @param list2
     * @param fieldName
     * @return
     */
    public static List<Object> differenceByKey(List<Object> list1,List<Object> list2,String fieldName) throws IllegalAccessException {
        Field field = getFirstElementField(list1, fieldName);
        Map<String,Object> map2 = TMSUtil.toMap(list2,fieldName);
        List<Object> result = new ArrayList<>();
        for (Object object : list1){
            Object filedValue = field.get(object);
            if (!map2.containsKey(fieldName)){
                result.add(object);
            }
        }
        return result;
    }


    /**
     * 求两个集合的差集
     * @param list1
     * @param list2
     * @return
     */
    public static List<Object> difference(List list1,List list2){
        List<Object> result = new ArrayList<>();

        for (Object object:list1){
            if (object!=null){
                result.add(object);
            }
        }

        result.removeAll(list2);
        return result;
    }



    /**
     * 检查是否是合法的邮箱地址
     *
     * @param mailAddress 待检验的邮箱地址
     * @return 如果是空字符串,或者不包含@符号,就是一个非法邮箱地址,返回false,否则返回true
     */
    public static boolean isValidMailAddress(String mailAddress) {
        if(StringUtils.isBlank(mailAddress))
            return false;

        String m = mailAddress.trim();
        int pos = m.indexOf("@");

        //找到@,且不是第一个,也不是最后一个
        return !(pos == -1 || pos == 0 || pos == m.length()-1);
    }


    /**
     * 获取参数中第一个不为空的字符串,如果返回空字符串,说明获取失败
     * @param args
     * @return
     */
    public static String getNotBlank(String ...args) {

        if (args == null) {
            return "";
        }

        for (String s : args) {
            if (StringUtils.isNotBlank(s)) {
                return s;
            }
        }

        return "";

    }

}

  

原文地址:https://www.cnblogs.com/lhp2012/p/5247431.html