View Javadoc
1   package org.andromda.utils.beans;
2   
3   import java.util.ArrayList;
4   import java.util.Collection;
5   import java.util.Collections;
6   import java.util.List;
7   
8   import org.andromda.core.common.ExceptionUtils;
9   import org.andromda.utils.beans.SortCriteria.Ordering;
10  import org.andromda.utils.beans.comparators.BeanComparator;
11  import org.apache.commons.collections.comparators.ComparatorChain;
12  
13  /**
14   * Provides bean sorting capabilities.
15   *
16   * <p>
17   * Sorts passed in Collections and returns
18   * sorted Lists.  Performs sorting for any
19   * Class that has an associated Comparator implementation defined.  If
20   * the Collection that is passed in, is not an instance of List, it will create
21   * a new ArrayList with the contents of the passed in Collection, before
22   * sorting occurs (since sorting can only be done on a java.util.List).
23   * </p>
24   *
25   * @author Chad Brandon
26   */
27  public class BeanSorter
28  {
29      /**
30       * Performs sorting of the collection by one property to
31       * sort with more than one property see {@link #sort(java.util.Collection, SortCriteria[])}.
32       *
33       * @see #sort(java.util.Collection, SortCriteria[])
34       *
35       * @param <T> Collection type
36       * @param beans the Collection of PersistentObjects to sort
37       * @param sortBy the property to sort by (i.e. firstName, etc). Can
38       *        be a nested property such as 'person.address.street'.
39       * @param ordering the ordering of the sorting (either {@link Ordering#ASCENDING}
40       *        or {@link Ordering#DESCENDING})
41       * @return the sorted List
42       */
43      public static <T> List<T> sort(
44          final Collection<T> beans,
45          final String sortBy,
46          final Ordering ordering)
47      {
48          return sort(
49              beans,
50              new SortCriteria[] {new SortCriteria(
51                      sortBy,
52                      ordering)});
53      }
54  
55      /**
56       * Performs sorting of the collection by one property to
57       * sort with more than one property see {@link #sort(java.util.Collection, SortCriteria[])}.
58       *
59       * @see #sort(java.util.Collection, SortCriteria[])
60       *
61       * @param <T> Collection type
62       * @param beans the Collection of PersistentObjects to sort
63       * @param sortBy the property to sort by (i.e. firstName, etc). Can
64       *        be a nested property such as 'person.address.street'.
65       * @param nullsFirst a flag indicating whether or not null values should be sorted to the beginning
66       *        or the ending of the list.
67       * @return the sorted List
68       */
69      public static <T> List<T> sort(
70          final Collection<T> beans,
71          final String sortBy,
72          final boolean nullsFirst)
73      {
74          return sort(
75              beans,
76              new SortCriteria[] {new SortCriteria(
77                      sortBy,
78                      nullsFirst)});
79      }
80  
81      /**
82       * Performs sorting of the collection by one property to
83       * sort with more than one property see {@link #sort(java.util.Collection, SortCriteria[])}.
84       *
85       * @see #sort(java.util.Collection, SortCriteria[])
86       *
87       * @param <T> Collection type
88       * @param beans the Collection of PersistentObjects to sort
89       * @param sortBy the property to sort by (i.e. firstName, etc). Can
90       *        be a nested property such as 'person.address.street'.
91       * @param ordering the ordering of the sorting (either {@link Ordering#ASCENDING}
92       *        or {@link Ordering#DESCENDING})
93       * @param nullsFirst a flag indicating whether or not null values should be sorted to the beginning
94       *        or the ending of the list.
95       * @return the sorted List
96       */
97      public static <T> List<T> sort(
98          final Collection<T> beans,
99          final String sortBy,
100         final Ordering ordering,
101         final boolean nullsFirst)
102     {
103         return sort(
104             beans,
105             new SortCriteria[] {new SortCriteria(
106                     sortBy,
107                     ordering,
108                     nullsFirst)});
109     }
110 
111     /**
112      * <p>
113      * Sorts the passed in Collection and returns
114      * a sorted List.  Performs SQL like sorting for any
115      * Class that has an associated Comparator implementation defined.  If
116      * the Collection that is passed in, is not an instance of List, it will create
117      * a new ArrayList with the contents of the passed in Collection, before
118      * sorting occurs.  Since sorting can only be done on a java.util.List.  If
119      * it is a list, then in-line sorting will occur of the list.
120      * </p>
121      *
122      * @param <T> Collection type
123      * @param beans the Collection of PersistentObjects to sort
124      * @param sortBy an array of SortCriteria.  This array of SortCriteria
125      * specifies which attributes to sort by.
126      * Attributes to sort by, MUST be simple attributes
127      * (i.e. name, type, etc, they can not be complex objects, but the properties can be
128      * nested simple types within associated beans).
129      *
130      * @return List the sorted List
131      */
132     public static <T> List<T> sort(
133         final Collection<T> beans,
134         final SortCriteria[] sortBy)
135     {
136         ExceptionUtils.checkNull(
137             "beans",
138             beans);
139         ExceptionUtils.checkNull(
140             "sortBy",
141             sortBy);
142 
143         if (sortBy.length == 0)
144         {
145             throw new IllegalArgumentException("sortBy must contain at least one value by which to sort");
146         }
147 
148         List<T> sorted = null;
149 
150         // IMPORTANT: do not replace this logic with new list creation, this allows for sorting of the passed
151         // in collection of beans (i.e. it allows this method to do "in-line" sorting), with the caller not  having
152         // to get the result of this method to get the sorted result, only if the collection is not a List instance
153         // will it need to use the result of this method to get the sorted collection.
154         if (!(beans instanceof List))
155         {
156             sorted = new ArrayList<T>(beans);
157         }
158         else
159         {
160             sorted = (List)beans;
161         }
162 
163         int sortByNum = sortBy.length;
164 
165         // - use the Comparator chain to provide SQL like sorting of properties
166         final ComparatorChain chain = new ComparatorChain();
167         for (int ctr = 0; ctr < sortByNum; ctr++)
168         {
169             final SortCriteria orderBy = sortBy[ctr];
170             chain.addComparator(new BeanComparator(orderBy));
171         }
172 
173         Collections.sort(
174             sorted,
175             chain);
176 
177         return sorted;
178     }
179 }