BeanSorter.java
package org.andromda.utils.beans;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.andromda.core.common.ExceptionUtils;
import org.andromda.utils.beans.SortCriteria.Ordering;
import org.andromda.utils.beans.comparators.BeanComparator;
import org.apache.commons.collections.comparators.ComparatorChain;
/**
* Provides bean sorting capabilities.
*
* <p>
* Sorts passed in Collections and returns
* sorted Lists. Performs sorting for any
* Class that has an associated Comparator implementation defined. If
* the Collection that is passed in, is not an instance of List, it will create
* a new ArrayList with the contents of the passed in Collection, before
* sorting occurs (since sorting can only be done on a java.util.List).
* </p>
*
* @author Chad Brandon
*/
public class BeanSorter
{
/**
* Performs sorting of the collection by one property to
* sort with more than one property see {@link #sort(java.util.Collection, SortCriteria[])}.
*
* @see #sort(java.util.Collection, SortCriteria[])
*
* @param <T> Collection type
* @param beans the Collection of PersistentObjects to sort
* @param sortBy the property to sort by (i.e. firstName, etc). Can
* be a nested property such as 'person.address.street'.
* @param ordering the ordering of the sorting (either {@link Ordering#ASCENDING}
* or {@link Ordering#DESCENDING})
* @return the sorted List
*/
public static <T> List<T> sort(
final Collection<T> beans,
final String sortBy,
final Ordering ordering)
{
return sort(
beans,
new SortCriteria[] {new SortCriteria(
sortBy,
ordering)});
}
/**
* Performs sorting of the collection by one property to
* sort with more than one property see {@link #sort(java.util.Collection, SortCriteria[])}.
*
* @see #sort(java.util.Collection, SortCriteria[])
*
* @param <T> Collection type
* @param beans the Collection of PersistentObjects to sort
* @param sortBy the property to sort by (i.e. firstName, etc). Can
* be a nested property such as 'person.address.street'.
* @param nullsFirst a flag indicating whether or not null values should be sorted to the beginning
* or the ending of the list.
* @return the sorted List
*/
public static <T> List<T> sort(
final Collection<T> beans,
final String sortBy,
final boolean nullsFirst)
{
return sort(
beans,
new SortCriteria[] {new SortCriteria(
sortBy,
nullsFirst)});
}
/**
* Performs sorting of the collection by one property to
* sort with more than one property see {@link #sort(java.util.Collection, SortCriteria[])}.
*
* @see #sort(java.util.Collection, SortCriteria[])
*
* @param <T> Collection type
* @param beans the Collection of PersistentObjects to sort
* @param sortBy the property to sort by (i.e. firstName, etc). Can
* be a nested property such as 'person.address.street'.
* @param ordering the ordering of the sorting (either {@link Ordering#ASCENDING}
* or {@link Ordering#DESCENDING})
* @param nullsFirst a flag indicating whether or not null values should be sorted to the beginning
* or the ending of the list.
* @return the sorted List
*/
public static <T> List<T> sort(
final Collection<T> beans,
final String sortBy,
final Ordering ordering,
final boolean nullsFirst)
{
return sort(
beans,
new SortCriteria[] {new SortCriteria(
sortBy,
ordering,
nullsFirst)});
}
/**
* <p>
* Sorts the passed in Collection and returns
* a sorted List. Performs SQL like sorting for any
* Class that has an associated Comparator implementation defined. If
* the Collection that is passed in, is not an instance of List, it will create
* a new ArrayList with the contents of the passed in Collection, before
* sorting occurs. Since sorting can only be done on a java.util.List. If
* it is a list, then in-line sorting will occur of the list.
* </p>
*
* @param <T> Collection type
* @param beans the Collection of PersistentObjects to sort
* @param sortBy an array of SortCriteria. This array of SortCriteria
* specifies which attributes to sort by.
* Attributes to sort by, MUST be simple attributes
* (i.e. name, type, etc, they can not be complex objects, but the properties can be
* nested simple types within associated beans).
*
* @return List the sorted List
*/
public static <T> List<T> sort(
final Collection<T> beans,
final SortCriteria[] sortBy)
{
ExceptionUtils.checkNull(
"beans",
beans);
ExceptionUtils.checkNull(
"sortBy",
sortBy);
if (sortBy.length == 0)
{
throw new IllegalArgumentException("sortBy must contain at least one value by which to sort");
}
List<T> sorted = null;
// IMPORTANT: do not replace this logic with new list creation, this allows for sorting of the passed
// in collection of beans (i.e. it allows this method to do "in-line" sorting), with the caller not having
// to get the result of this method to get the sorted result, only if the collection is not a List instance
// will it need to use the result of this method to get the sorted collection.
if (!(beans instanceof List))
{
sorted = new ArrayList<T>(beans);
}
else
{
sorted = (List)beans;
}
int sortByNum = sortBy.length;
// - use the Comparator chain to provide SQL like sorting of properties
final ComparatorChain chain = new ComparatorChain();
for (int ctr = 0; ctr < sortByNum; ctr++)
{
final SortCriteria orderBy = sortBy[ctr];
chain.addComparator(new BeanComparator(orderBy));
}
Collections.sort(
sorted,
chain);
return sorted;
}
}