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);
}
}
}

Java EntityMapper的更多相关文章

  1. Spark案例分析

    一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...

  2. 使用jhipster 加速java web开发

    jhipster,中文释义: Java 热爱者! JHipster is a development platform to quickly generate, develop, & depl ...

  3. 故障重现(内存篇2),JAVA内存不足导致频繁回收和swap引起的性能问题

    背景起因: 记起以前的另一次也是关于内存的调优分享下   有个系统平时运行非常稳定运行(没经历过大并发考验),然而在一次活动后,人数并发一上来后,系统开始卡. 我按经验开始调优,在每个关键步骤的加入如 ...

  4. Elasticsearch之java的基本操作一

    摘要   接触ElasticSearch已经有一段了.在这期间,遇到很多问题,但在最后自己的不断探索下解决了这些问题.看到网上或多或少的都有一些介绍ElasticSearch相关知识的文档,但个人觉得 ...

  5. 论:开发者信仰之“天下IT是一家“(Java .NET篇)

    比尔盖茨公认的IT界领军人物,打造了辉煌一时的PC时代. 2008年,史蒂夫鲍尔默接替了盖茨的工作,成为微软公司的总裁. 2013年他与微软做了最后的道别. 2013年以后,我才真正看到了微软的变化. ...

  6. 故障重现, JAVA进程内存不够时突然挂掉模拟

    背景,服务器上的一个JAVA服务进程突然挂掉,查看产生了崩溃日志,如下: # Set larger code cache with -XX:ReservedCodeCacheSize= # This ...

  7. 死磕内存篇 --- JAVA进程和linux内存间的大小关系

    运行个JAVA 用sleep去hold住 package org.hjb.test; public class TestOnly { public static void main(String[] ...

  8. 【小程序分享篇 一 】开发了个JAVA小程序, 用于清除内存卡或者U盘里的垃圾文件非常有用

    有一种场景, 手机内存卡空间被用光了,但又不知道哪个文件占用了太大,一个个文件夹去找又太麻烦,所以我开发了个小程序把手机所有文件(包括路径下所有层次子文件夹下的文件)进行一个排序,这样你就可以找出哪个 ...

  9. Java多线程基础学习(二)

    9. 线程安全/共享变量——同步 当多个线程用到同一个变量时,在修改值时存在同时修改的可能性,而此时该变量只能被赋值一次.这就会导致出现“线程安全”问题,这个被多个线程共用的变量称之为“共享变量”. ...

随机推荐

  1. vue-cli 2.92版本 没有dev.server.js

    在webpack.dev.conf.js 文件中 //首先 const express = require('express') const app = express() var appData = ...

  2. springboot之jar包部署步骤

    eclipse中: 1.单击整个项目 run as - maven clean - maven install 2.找到项目所在的路径 找到所有的jar包 3.把jar包放到linux对应的文件夹 l ...

  3. MySQL中group by , sum , case when then 的使用

    在我们使用数据库的时候,可能会遇到需要进行统计的情况. 比如需要统计一下,下表中各个年份的胜负场数. 遇到这样的情况,我们应该怎么办呢? 在mysql中我们可以使用group by sum  case ...

  4. [C++ Primer Plus] 第5章、循环和关系表达式(一)程序清单——指针自加减优先级

    程序5.4 #include<iostream> using namespace std; ; void main() { long long factorials[Size]; fact ...

  5. bzoj 5185 Lifeguards - 动态规划 - 贪心

    题目传送门 传送点I 传送点II 题目大意 给定$n$个区间,问恰好删去其中$k$个,剩下的区间的并的最大总长度. 显然被包含的区间一定不优.再加上被包含的区间对计数不友好.直接把它删掉. 注意到题目 ...

  6. (转)Awesome Human Pose Estimation

    Awesome Human Pose Estimation 2018-10-08 11:02:35 Copied from: https://github.com/cbsudux/awesome-hu ...

  7. .NET Core 配置GC工作模式与内存的影响

    .NET Core 配置GC工作模式与内存的影响 .NET Core GC 原文:https://blog.markvincze.com/troubleshooting-high-memory-usa ...

  8. 使用excel估计GARCH模型参数——以GARCH(1,1)为例

    本文的知识点:使用excel求解GARCH模型的系数,以GARCH模型为例,主要采用的是极大似然估计法MLE. 同时给出了R语言的输出结果作为对照验证.     参考了:http://investex ...

  9. linux软件管理之概述

    软件包管理 ====================================================================================安装/查询/卸载 一 ...

  10. 压力测试+接口测试(工具jmeter)

      jmeter是apache公司基于java开发的一款开源压力测试工具,体积小,功能全,使用方便,是一个比较轻量级的测试工具,使用起来非常简单.因 为jmeter是java开发的,所以运行的时候必须 ...