/* * NOTE: This copyright does *not* cover user programs that use HQ * program services by normal system calls through the application * program interfaces provided as part of the Hyperic Plug-in Development * Kit or the Hyperic Client Development Kit - this is merely considered * normal use of the program, and does *not* fall under the heading of * "derived work". * * Copyright (C) [2004, 2005, 2006], Hyperic, Inc. * This file is part of HQ. * * HQ is free software; you can redistribute it and/or modify * it under the terms version 2 of the GNU General Public License as * published by the Free Software Foundation. This program is distributed * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. */ package org.hyperic.util; import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Comparator; /** * This is a comparator that can be used for in-process sorting of a * collection of java beans. * */ public final class JavaBeanPropertyComparator implements Comparator { /** * Constant value representing an ascending sort. */ public static final int ASCENDING = 0; /** * Constant value representing a descending sort. */ public static final int DESCENDING = 1; // member data private String propertyName; private int sortOrder = ASCENDING; /** * Construct a comparator with <code>{@link ASCENDING}</code> sort * order and the given property name. * * @param propertyName the name of the property to use for sorting */ public JavaBeanPropertyComparator(String propertyName) { this(propertyName, ASCENDING); } /** * Construct a comparator with the given sort order and property * name. * * @param propertyName the name of the property to use for sorting * @param sortOrder <code>{@link ASCENDING}</code> or <code>{@link * DESCENDING}</code> */ public JavaBeanPropertyComparator(String propertyName, int sortOrder) { if ( null == propertyName || 0 == propertyName.length() ) { throw new IllegalArgumentException ("propertyName cannot be null or empty"); } this.propertyName = propertyName; this.sortOrder = sortOrder; } /** * <p>If both <code>o1</code> and <code>o2</code> have the * appropriate java bean property, compare the String * representation of that property value on each.</p> * * <p>If one of the objects has the property and the other * doesn't, the one with the property will be considered "less" * than the one without the property. If neither object has the * property, 0 will be returned.</p> * * <p>If the sort order is <code>DESCENDING</code>, the value * returned will be negated.</p> * * @param o1 the first java bean to compare * @param o2 the second java bean to compare * * @return the value of the string-comparison of the two bean's * property values */ public int compare(Object o1, Object o2) { String val1 = getProperty(o1); String val2 = getProperty(o2); int retVal; if (null == val1) { if (null == val2) { retVal = 0; } else { // o2 is "less" retVal = 1; } } else { if (null == val2) { // o1 is "less" retVal = -1; } else { retVal = val1.compareTo(val2); } } if (ASCENDING == sortOrder) { return retVal; } else { return 0 - retVal; } } /** * Return true if the passed-in <code>obj</code> is the same as * this. * * @param obj the object being tested for equality to this * * @return true if the object is the same as this, false otherwise */ public boolean equals(Object obj) { try { JavaBeanPropertyComparator that = (JavaBeanPropertyComparator)obj; return (this.propertyName.equals(that.propertyName) && this.sortOrder == that.sortOrder); } catch (ClassCastException e) { return false; } } //---------------------------------------------------------------- //-- private helpers //---------------------------------------------------------------- private String getProperty(Object obj) { try { PropertyDescriptor pd = new PropertyDescriptor( propertyName, obj.getClass() ); Method m = pd.getReadMethod(); Object value = m.invoke(obj, (Object[])null/* method args */); return String.valueOf(value); } catch (IntrospectionException e) { // no such property return null; } catch (IllegalAccessException e) { // no such property return null; } catch (InvocationTargetException e) { // no such property return null; } } //---------------------------------------------------------------- //-- for testing //---------------------------------------------------------------- public static void main(String[] args) { JavaBeanPropertyComparator asc = new JavaBeanPropertyComparator("foo", ASCENDING); JavaBeanPropertyComparator desc = new JavaBeanPropertyComparator("foo", DESCENDING); Foo foo1 = new Foo("aaa"); Foo foo2 = new Foo("aaa"); Foo foo3 = new Foo("bbb"); NoFoo noFoo = new NoFoo(); System.out.println("ascending compare(foo1, foo2)=" + asc.compare(foo1, foo2)); System.out.println("ascending compare(foo1, foo3)=" + asc.compare(foo1, foo3)); System.out.println("ascending compare(foo1, noFoo)=" + asc.compare(foo1, noFoo)); System.out.println("descending compare(foo1, foo2)=" + desc.compare(foo1, foo2)); System.out.println("descending compare(foo1, foo3)=" + desc.compare(foo1, foo3)); System.out.println("descending compare(foo1, noFoo)=" + desc.compare(foo1, noFoo)); } private static class Foo { private String foo; public Foo(String foo) { this.foo = foo; } public void setFoo(String foo) { this.foo = foo; } public String getFoo() { return foo; } } private static class NoFoo { public NoFoo() { } } } // EOF