package com.github.protobufel.test.util;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.assertj.core.util.Objects;
import org.assertj.core.util.Preconditions;
import org.assertj.core.util.introspection.Introspection;
//TODO remove when AssertJ usingElementComparatorOnFields fixed
public final class BeanPropertiesComparator<T> implements Comparator<T> {
private final List<String> propNames;
private List<Method> methods;
private BeanPropertiesComparator(final String... propNames) {
Preconditions.checkNotNullOrEmpty(propNames);
final ArrayList<String> args = new ArrayList<String>();
Collections.addAll(args, propNames);
this.propNames = Collections.unmodifiableList(args);
this.methods = null;
}
public static <T> BeanPropertiesComparator<T> of(final String... propNames) {
return new BeanPropertiesComparator<T>(propNames);
}
@Override
public int compare(T o1, T o2) {
if (o1 == o2) {
return 0;
} else if (o1 == null) {
return (o2 == null) ? 0 : -1;
} else if (o2 == null) {
return (o1 == null) ? 0 : 1;
}
for (Method method : getMethods(o1)) {
try {
if (!Objects.areEqual(method.invoke(o1), method.invoke(o1))) {
// this comparator is for custom equality, so either -1, or 1 would do!
return -1;
}
} catch (Exception e) {
new RuntimeException(e);
}
}
return 0;
}
private List<Method> getMethods(final T object) {
if (this.methods == null) {
final List<Method> methods = new ArrayList<Method>(propNames.size());
for (String propName : propNames) {
final Method method =
Preconditions.checkNotNull(Introspection.getProperty(propName, object)
.getReadMethod());
methods.add(method);
}
this.methods = Collections.unmodifiableList(methods);
}
return this.methods;
}
}