package de.skuzzle.polly.sdk.util;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Comparator;
/**
* <p>Type unsafe comparator implementation that uses reflection to retrieve an objects
* getter method and then compares its result to the result of the others object getter.
* The getter can be specified as String.</p>
*
* <p>There are several things that can go wrong by using this comparator. Any violation
* of the following rules will result in an {@link CompareException} being thrown.</p>
*
* <p>First, both objects that are being compared must have a getter method with no
* parameter and same return type with the name specified in the constructor of this
* class. Second, the return type of that getter method must implement the
* {@link Comparable} interface. Third, there are other things that can go wrong when
* using exceptions such like illegal access when a SecurityManager is used or
* the invoked methods themself throw any runtime exceptions. This implementations does
* not care for them and just delegates them to the caller, causing the compare-process
* for those objects to fail.</p>
*
* @author Simon
* @since 0.9.1
*/
public class ReflectionComparator implements Comparator<Object>{
private String field;
private boolean desc;
/**
* Creates a new Comparator that can sort objects that have a getter with the given
* fieldName. The created Comparator will always sort ascending.
*
* @param fieldName The name of the getter that will be used as sort key.
*/
public ReflectionComparator(String fieldName) {
this(fieldName, false);
}
/**
* Creates a new Comparator that can sort objects that have a getter with the given
* fieldName. If desc is set <code>true</code>, this comparator will sort
* descending, ascending otherwise.
*
* @param fieldName The name of the getter that will be used as sort key.
* @param desc The sort direction.
*/
public ReflectionComparator(String fieldName, boolean desc) {
this.field = fieldName;
this.desc = desc;
}
public String getField() {
return this.field;
}
@SuppressWarnings("unchecked")
@Override
public int compare(Object o1, Object o2) {
try {
Method getter1 = o1.getClass().getMethod(this.field);
Method getter2 = o2.getClass().getMethod(this.field);
Comparable<Object> result1 = (Comparable<Object>) getter1.invoke(o1);
Comparable<Object> result2 = (Comparable<Object>) getter2.invoke(o2);
if (this.desc) {
return result2.compareTo(result1);
} else {
return result1.compareTo(result2);
}
} catch (NoSuchMethodException e) {
throw new CompareException("Specified getter '" + //$NON-NLS-1$
this.field + "' does not exist", e); //$NON-NLS-1$
} catch (SecurityException e) {
throw new CompareException(e);
} catch (IllegalAccessException e) {
throw new CompareException(e);
} catch (IllegalArgumentException e) {
throw new CompareException(e);
} catch (InvocationTargetException e) {
throw new CompareException(e);
}
}
}