zoukankan      html  css  js  c++  java
  • Java EntityMapper

    package org.rx.util;
    
    import org.rx.common.Func2;
    import org.rx.common.Action2;
    import org.rx.common.Func1;
    import org.rx.common.NQuery;
    import org.rx.security.MD5Util;
    
    import java.lang.reflect.Array;
    import java.lang.reflect.Method;
    import java.util.*;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.ConcurrentMap;
    
    /**
     * Created by wangxiaoming on 2016/3/11.
     */
    public class EntityMapper {
        //region NestedTypes
        private static class MapEntity {
            public Func2<String, String, Boolean> MembersMatcher;
            public Object                         PostProcessor;
            public HashSet<String>                IgnoreNames;
        }
    
        private static class DefaultMatcher implements Func2<String, String, Boolean> {
            @Override
            public Boolean invoke(String arg1, String arg2) {
                return arg1.equals(arg2);
            }
        }
        //endregion
    
        //region Fields
        private static final String                     GET                = "get", SET = "set";
        private static final int                        getDefaultWhenNull = 1 << 0, putNewWhenNull = 1 << 1;
        private static final MapEntity                  Default;
        private static ConcurrentMap<String, MapEntity> Config;
        //endregion
    
        //region Methods
        static {
            Default = new MapEntity();
            Default.IgnoreNames = new HashSet<>();
            Default.IgnoreNames.add("getClass");
            Default.MembersMatcher = new DefaultMatcher();
            Config = new ConcurrentHashMap<>();
        }
    
        private static MapEntity getConfig(Class<?> tFrom, Class<?> tTo, int flags) {
            String key = getKey(tFrom, tTo);
            MapEntity map = Config.get(key);
            if (map == null) {
                if ((flags & getDefaultWhenNull) == getDefaultWhenNull) {
                    return Default;
                }
                if ((flags & putNewWhenNull) == putNewWhenNull) {
                    Config.putIfAbsent(key, map = new MapEntity());
                    map.MembersMatcher = Default.MembersMatcher;
                }
            }
            return map;
        }
    
        private static String getKey(Class<?> tFrom, Class<?> tTo) {
            return MD5Util.md5Hex(tFrom.getName() + tTo.getName());
        }
    
        public static <T> T createInstance(Class<T> type) {
            try {
                return type.newInstance();
            } catch (ReflectiveOperationException ex) {
                throw new RuntimeException(ex);
            }
        }
        //endregion
    
        //region MapMethods
        public synchronized static <TF, TT> void setMembersMatcher(Class<TF> tFrom, Class<TT> tTo,
                                                                   Func2<String, String, Boolean> membersMatcher,
                                                                   Action2<TF, TT> postProcessor) {
            MapEntity map = getConfig(tFrom, tTo, putNewWhenNull);
            map.MembersMatcher = membersMatcher == null ? Default.MembersMatcher : membersMatcher;
            map.PostProcessor = postProcessor;
        }
    
        public synchronized static void setIgnoreMembers(Class<?> tFrom, Class<?> tTo, String... ignoreNames) {
            MapEntity map = getConfig(tFrom, tTo, putNewWhenNull);
            map.IgnoreNames = new HashSet<>(Arrays.asList(ignoreNames));
            map.IgnoreNames.add("getClass");
        }
    
        public static <TF, TT> TT[] map(Collection<TF> from, Class<TT> toType) {
            List<TT> toSet = new ArrayList<>();
            for (Object o : from) {
                toSet.add(map(o, toType));
            }
            TT[] x = (TT[]) Array.newInstance(toType, toSet.size());
            toSet.toArray(x);
            return x;
        }
    
        public static <TF, TT> TT map(TF from, Class<TT> toType) {
            return map(from, createInstance(toType));
        }
    
        public static <TF, TT> TT map(TF from, TT to) {
            return map(from, to, false);
        }
    
        public static <TF, TT> TT map(TF from, TT to, boolean skipNull) {
            Class<?> tFrom = from.getClass(), tTo = to.getClass();
            final MapEntity map = getConfig(tFrom, tTo, getDefaultWhenNull);
    
            NQuery<Method> fq = new NQuery<>(tFrom.getMethods()).where(new Func1<Method, Boolean>() {
                @Override
                public Boolean invoke(Method arg) {
                    String fName = arg.getName();
                    return !map.IgnoreNames.contains(fName) && fName.startsWith(GET);
                }
            });
            NQuery<Method> tq = new NQuery<>(tTo.getMethods()).where(new Func1<Method, Boolean>() {
                @Override
                public Boolean invoke(Method arg) {
                    return arg.getName().startsWith(SET);
                }
            });
    
            for (Method fMethod : fq) {
                String fName = fMethod.getName();
                final String tName = SET + fName.substring(3);
                //App.logInfo("EntityMapper Step1 %s", fName);
    
                Method tMethod = tq.where(new Func1<Method, Boolean>() {
                    @Override
                    public Boolean invoke(Method arg) {
                        return map.MembersMatcher.invoke(tName, arg.getName());
                    }
                }).firstOrDefault();
                Class<?>[] tArgs;
                if (tMethod == null || (tArgs = tMethod.getParameterTypes()).length != 1) {
                    //App.logInfo("EntityMapper %s Miss %s.%s", tTo.getSimpleName(), tFrom.getSimpleName(), tName);
                    continue;
                }
                //App.logInfo("EntityMapper Step2 %s to %s", fName, tName);
    
                try {
                    Object value = fMethod.invoke(from);
                    if (value == null && skipNull) {
                        continue;
                    }
                    value = App.changeType(value, tArgs[0]);
                    tMethod.invoke(to, value);
                } catch (ReflectiveOperationException ex) {
                    throw new RuntimeException(ex);
                }
            }
    
            if (map.PostProcessor != null) {
                Action2<TF, TT> postProcessor = (Action2<TF, TT>) map.PostProcessor;
                postProcessor.invoke(from, to);
            }
            return to;
        }
        //endregion
    
        public static void trim(Object entity) {
            Class<?> type = entity.getClass();
            NQuery<Method> fq = new NQuery<>(type.getMethods()).where(new Func1<Method, Boolean>() {
                @Override
                public Boolean invoke(Method arg) {
                    return arg.getName().startsWith(GET) && arg.getReturnType().equals(String.class);
                }
            });
    
            for (Method method : fq) {
                try {
                    String value = (String) method.invoke(entity);
                    if (App.isNullOrEmpty(value)) {
                        continue;
                    }
                    method = type.getMethod(SET + method.getName().substring(3), String.class);
                    method.invoke(entity, value.trim());
                } catch (ReflectiveOperationException ex) {
                    throw new RuntimeException(ex);
                }
            }
        }
    
        public static Object getProperty(Object entity, String propName) {
            try {
                Method method = entity.getClass()
                        .getMethod(GET + propName.substring(0, 1).toUpperCase() + propName.substring(1));
                return method.invoke(entity);
            } catch (ReflectiveOperationException ex) {
                throw new RuntimeException(ex);
            }
        }
    }
  • 相关阅读:
    基于Asp.Net webApi owin oauth2的实现
    动态赋值
    C#生成二维码
    深度学习中反卷积层(转置卷积)引起的棋盘格噪声
    batch normalization 批归一化 --- 一个硬币的两面
    FFMPEG常用命令-格式转换-持续更新中
    [译]CRF和QP的区别
    读懂NCHW和NHWC
    [译]GPUView
    有一次接口设计
  • 原文地址:https://www.cnblogs.com/Googler/p/7340372.html
Copyright © 2011-2022 走看看