Skip to content

Instantly share code, notes, and snippets.

@nekocode
Created May 9, 2017 09:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nekocode/d4159b5ed0ba03ae44dc11409458c4ff to your computer and use it in GitHub Desktop.
Save nekocode/d4159b5ed0ba03ae44dc11409458c4ff to your computer and use it in GitHub Desktop.
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
/**
* Modified from {@link <a href="http://stackoverflow.com/a/32817115/5729581"/>}
*
* @author nekocode (nekocode.cn@gmail.com)
*/
public class DiffUtils {
private static final HashMap<Class, ArrayList<GetterAndSetter>> methodMap = new HashMap<>();
public static <T> void compareAndApplyDifferences(T target, T source) {
final Class<?> c1 = target.getClass();
final Class<?> c2 = source.getClass();
if (!c1.equals(c2)) {
return;
}
ArrayList<GetterAndSetter> getterAndSetters = methodMap.get(c1);
if (getterAndSetters == null) {
/*
Cache Getters & Setters
*/
final HashMap<String, Method> gettersMap = new HashMap<>();
final ArrayList<Method> setters = new ArrayList<>();
final Method[] methods = c1.getMethods();
for (Method method : methods) {
if (isGetter(method)) {
final String methodName = method.getName();
if (methodName.startsWith("is")) {
gettersMap.put(methodName.substring(2), method);
} else if (methodName.startsWith("get")) {
gettersMap.put(methodName.substring(3), method);
}
} else if (isSetter(method)) {
setters.add(method);
}
}
getterAndSetters = new ArrayList<>();
if (gettersMap.size() > 0 && setters.size() > 0) {
for (Method setter : setters) {
final Method getter = gettersMap.get(setter.getName().substring(3));
if (getter != null) {
getterAndSetters.add(new GetterAndSetter(getter, setter));
}
}
}
methodMap.put(c1, getterAndSetters);
}
for (GetterAndSetter getterAndSetter : getterAndSetters) {
final Method getter = getterAndSetter.getter;
final Method setter = getterAndSetter.setter;
Object getterResult1, getterResult2;
try {
getterResult1 = getter.invoke(target);
} catch (Exception ignored) {
getterResult1 = null;
}
try {
getterResult2 = getter.invoke(source);
} catch (Exception ignored) {
getterResult2 = null;
}
if (getterResult2 != null && !getterResult2.equals(getterResult1)) {
// Copy value
try {
setter.invoke(target, getterResult2);
} catch (Exception ignored) {
}
}
}
}
private static boolean isGetter(Method method) {
if (!(method.getName().startsWith("get") || method.getName().startsWith("is")))
return false;
if (method.getParameterTypes().length != 0)
return false;
if (void.class.equals(method.getReturnType()))
return false;
return true;
}
private static boolean isSetter(Method method) {
if (!method.getName().startsWith("set"))
return false;
if (method.getParameterTypes().length != 1)
return false;
return true;
}
private static class GetterAndSetter {
Method getter;
Method setter;
GetterAndSetter(Method getter, Method setter) {
this.getter = getter;
this.setter = setter;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment