001    package edu.nrao.sss.sort;
002    
003    import java.util.Comparator;
004    
005    /**
006     * A {@link SortKey sort key} and {@link Comparator comparator} that works with
007     * the {@code Integer}s returned by a method that is found reflectively.
008     * <p>
009     * Clients of this class must provide the name of a public, no argument, method
010     * that returns a {@code Integer} and that is present in classes of the
011     * parameterized type {@code T}.  The method created from that name is called
012     * on the objects to be compared, and the integers returned from those methods
013     * are what is actually compared.</p>
014     * <p>
015     * Because this class is a {@link SortKey}, you may configure its instances with
016     * a particular {@code SortOrder}.  You may place instances of this
017     * class in a {@link CompoundComparator}.</p>
018     * <p>
019     * <b><u>Example</u></b><br/>
020     * Let there be a class, <tt>Person</tt>, that has the following
021     * attributes, each of which is an <tt>integer</tt>: 
022     * <tt>height (cm), weight (kg), age</tt>.
023     * Furthermore, assume the normal convention
024     * for the getters (e.g., <tt>getAge()</tt>).  You could sort a collection of
025     * people by age, then height, then weight, without writing any new
026     * classes by doing this:</p>
027     * <pre>
028     *   ReflectiveIntSortKey&lt;Person&gt; ageKey =
029     *     new ReflectiveIntSortKey&lt;Person&gt;("getAge");
030     *     
031     *   ReflectiveIntSortKey&lt;Person&gt; heightKey =
032     *     new ReflectiveIntSortKey&lt;Person&gt;("getHeight");
033     *     
034     *   ReflectiveIntSortKey&lt;Person&gt; weightKey =
035     *     new ReflectiveIntSortKey&lt;Person&gt;("getWeight");
036     *     
037     *   CompoundComparator&lt;Person&gt; comparator =
038     *     new CompoundComparator&lt;Person&gt;(ageKey, heightKey, weightKey);
039     *     
040     *   Collections.sort(population, comparator);
041     * </pre>
042     * <p>
043     * <b>Version Info:</b>
044     * <table style="margin-left:2em">
045     *   <tr><td>$Revision: 593 $</td></tr>
046     *   <tr><td>$Date: 2007-05-07 15:54:14 -0600 (Mon, 07 May 2007) $</td></tr>
047     *   <tr><td>$Author: dharland $</td></tr>
048     * </table></p>
049     * 
050     * @author David M. Harland
051     * @since 2007-05-07
052     */
053    public final class ReflectiveIntSortKey<T>
054      extends IntSortKey
055      implements Comparator<T>
056    {
057      private ReflectiveSortHelper<Integer, T> helper;
058      
059      /**
060       * Creates a new instance that will base its comparison on the {@code Integer}
061       * returned by the method with the given name.
062       *  
063       * @param methodName the name of a public, no argument, method that belongs
064       *                   to objects of type {@code T} and that returns an
065       *                   {@code Integer} (or {@code int}).  If there is any
066       *                   trouble creating or calling the method with this name,
067       *                   it will be treated as if it returns an {@code Integer}
068       *                   of {@link Integer#MIN_VALUE}.
069       */
070      public ReflectiveIntSortKey(String methodName)
071      {
072        helper = new ReflectiveSortHelper<Integer, T>(methodName,Integer.MIN_VALUE);
073      }
074      
075      /**
076       * Sets the name of the method used for making comparisons.
077       * 
078       * @param newMethodName the name of a public, no argument, method that belongs
079       *                      to objects of type {@code T} and that returns an
080       *                      {@code Integer} (or {@code in}).  If there is any
081       *                      trouble creating or calling the method with this name,
082       *                      it will be treated as if it returns a {@code Integer}
083       *                      of {@link Integer#MIN_VALUE}.
084       */
085      public void setMethodName(String newMethodName)
086      {
087        helper.setMethodName(newMethodName);
088      }
089      
090      /* (non-Javadoc)
091       * @see Comparator#compare(Object, Object)
092       */
093      public int compare(T o1, T o2)
094      {
095        return compareObjects(helper.getValue(o1), helper.getValue(o2));
096      }
097    }