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 }