Created
May 9, 2017 09:07
-
-
Save nekocode/d4159b5ed0ba03ae44dc11409458c4ff to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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