zoukankan      html  css  js  c++  java
  • 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 "";
    
        }
    
    }
    

      

  • 相关阅读:
    inotifywait实时监控文件目录
    centos7支持xming
    ssh目录权限说明
    利用xinetd实现简单web服务器
    python3 使用http.server秒速搭建web服务器
    linux FFMPEG 摄像头采集数据推流
    Linux nginx+rtmp服务器配置实现直播点播
    Nginx中加入nginx-rtmp-module
    ubuntu查看屏幕分辨率
    运用设计原则编写可测试性的代码
  • 原文地址:https://www.cnblogs.com/lhp2012/p/5247431.html
Copyright © 2011-2022 走看看