/*
* file: ReflexiveComparator.java
* package: oreilly.hcj.reflection
*
* This software is granted under the terms of the Common Public License,
* CPL, which may be found at the following URL:
* http://www-124.ibm.com/developerworks/oss/CPLv1.0.htm
*
* Copyright(c) 2003-2005 by the authors indicated in the @author tags.
* All Rights are Reserved by the various authors.
*
########## DO NOT EDIT ABOVE THIS LINE ########## */
package oreilly.hcj.reflection;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.Comparator;
/**
* Creates a comparator that sorts the target objects based upon the value of a specific
* property. <b>Note: this comparator imposes orderings that are inconsistent with
* equals. This is because the comparator is set up reflexively and may not match the
* comparisons in the equals method.</b>
*
* @author $author$
* @version $Revision: 1.9 $
*/
public class ReflexiveComparator implements Comparator {
/** Holds error message for non comparable sortProperty. */
private static final String ERR_COMPARABLE =
"The sortProperty doesn't implement java.lang.Comparable"; //$NON-NLS-1$
/** Holds value of property dataType. */
private Class dataType;
/** Holds value of property sortProperty. */
private PropertyDescriptor sortProperty;
/** Holds value of property ascending. */
private boolean ascending;
/**
* Creates a new instance of ReflexiveComparator.
*
* @param dataType Class which this comparator will be sorting.
* @param sortProperty The property descriptor of the class to use to sort.
* @param ascending Whether to sort in ascending order (default) or not. Pass false
* to sort in descending order.
*
* @throws IllegalArgumentException DOCUMENT ME!
*/
public ReflexiveComparator(final Class dataType,
final PropertyDescriptor sortProperty,
final boolean ascending) {
this.dataType = dataType;
this.sortProperty = sortProperty;
this.ascending = ascending;
if (!(sortProperty.getPropertyType().isPrimitive())) {
if (!(Comparable.class.isAssignableFrom(this.sortProperty.getPropertyType()))) {
throw new IllegalArgumentException(ERR_COMPARABLE);
}
}
}
// /**
// * Creates a new instance of ReflexiveComparator.
// *
// * @param dataType Class which this comparator will be sorting.
// * @param sortProperty The name of the property of the class to use to sort. This
// * property must implement the interface{@link java.lang.Comparable
// * java.lang.Comparable}.
// * @param ascending Whether to sort in ascending order (default) or not. Pass false
// * to sort in descending order.
// */
// public ReflexiveComparator(final Class dataType, final String sortProperty,
// final boolean ascending) {
// this(dataType, PropertyDescriptorMap.getDescriptor(dataType, sortProperty),
// ascending);
// }
/**
* Setter for property ascending.
*
* @param ascending New value of property ascending.
*/
public void setAscending(final boolean ascending) {
this.ascending = ascending;
}
/**
* Getter for property ascending.
*
* @return Value of property ascending.
*/
public boolean isAscending() {
return this.ascending;
}
/**
* Setter for property tgtClass.
*
* @param dataType New value of property tgtClass.
*/
public void setDataType(Class dataType) {
this.dataType = dataType;
}
/**
* Getter for property tgtClass.
*
* @return Value of property tgtClass.
*/
public Class getDataType() {
return this.dataType;
}
/**
* Setter for property sortProperty.
*
* @param sortProperty New value of property sortProperty.
*/
public void setSortProperty(PropertyDescriptor sortProperty) {
this.sortProperty = sortProperty;
}
/**
* Getter for property sortProperty.
*
* @return Value of property sortProperty.
*/
public PropertyDescriptor getSortProperty() {
return this.sortProperty;
}
/**
* Compares its two arguments for order. Sorts according to the following design.
* Note that if the ascending property is false, the values for +1 or -1 will be
* reversed.
*
* <ul>
* <li>
* Giving null for the first argument will always give a -1 reply.
* </li>
* <li>
* Giving null for the second argument will always give a +1 reply.
* </li>
* <li>
* Giving null for the both arguments will always give a 0 reply.
* </li>
* <li>
* Objects whose sortProperty contains null will give a -1 reply relative to objects
* with a non-null sortProperty.
* </li>
* <li>
* If both objects' sort property are not null, The values of the sort properties
* will be compared.
* </li>
* </ul>
*
*
* @param x Object to compare.
* @param y Second object to compare.
*
* @return A value of +1, -1 or 0 depending on the compare.
*/
public int compare(final Object x, final Object y) {
if (ascending) {
return compareHelper(x, y);
} else {
return (0 - compareHelper(x, y));
}
}
/**
* Perform the raw compare.
*
* @param x Object to compare.
* @param y Second object to compare.
*
* @return The result of the comparison
*
* @throws RuntimeException If there is an exception during ocmparison.
*
* @see Method {@link mirror.utilties.ReflexiveComparator.compare(Object, Object)}
*/
private int compareHelper(final Object x, final Object y) {
try {
if ((x != null) && (y == null)) {
return -1;
} else if ((x == null) && (y != null)) {
return -1;
} else if ((x == null) && (y == null)) {
return 0;
}
Object xVal = this.sortProperty.getReadMethod()
.invoke(x, null);
Object yVal = this.sortProperty.getReadMethod()
.invoke(y, null);
if ((xVal != null) && (yVal == null)) {
return -1;
} else if ((xVal == null) && (yVal != null)) {
return -1;
} else if ((xVal == null) && (yVal == null)) {
return 0;
}
return ((Comparable)xVal).compareTo(yVal);
} catch (final InvocationTargetException ex) {
throw new RuntimeException(ex);
} catch (final IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
}
/* ########## End of File ########## */
|