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 }