commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "James Carman" <ja...@carmanconsulting.com>
Subject RE: [collections] [beanutils] Multi property BeanComparator
Date Fri, 17 Mar 2006 03:56:00 GMT
What about using a "chained" comparator?  Wouldn't that do what you want?
Yes, it's not fun to set up, but you could create a helper method...

public void sort( List beans, String[] properties )
{
  // Create a bean comparator for each property.
  // Create a chained comparator from the bean comparators.
  // Sort the list
...  
}




-----Original Message-----
From: Stephen Colebourne [mailto:scolebourne@btopenworld.com] 
Sent: Thursday, March 16, 2006 7:06 PM
To: Jakarta Commons Users List
Subject: Re: [collections] [beanutils] Multi property BeanComparator

This is an interesting idea, to group multiple property comparisons in one.

It no longer fits in [collections] however as the bean code from 
collections has moved to [beanutils] in their bean-collections jar.

The problem with beanutils is that it is not well maintained at the moment.

I recommend that you raise a bugzilla enhancement request for beanutils 
and attach your code as a patch. That way the idea can be looked at when 
someone has a chance.

Stephen


MATHUS Baptiste wrote:
> Hi everybody,
> 
> I recently needed to be able to sort a list of beans on many properties.
So I thought I would try and pick one of the collections comparators.  
> 
> I had to to the sorting close to the sql way : be able to sort on n
properties, some ascending, some descending.
> 
> I haven't found what I'm looking for (:p), but I found some comparators I
used to do this : I used BeanComparator, NullComparator and ComparatorChain
to create a class : MultiPropertyBeanComparator.
> 
> Is there already something in one of the commons package that could be
used instead of it ? 
> 
> If not, I'd be glad to contribute the small piece of code if wanted. It
has dependencies against commons-beanutils (BeanComparator, which is moving
from one package to another at the moment, no ?) and commons-lang
(StringUtils.isBlank()). I think some things might not satisfactory for
everybody, but hey, could still be improved without problems, that's not big
work :p.
> 
> Here it is :
> 
> =======================================
> import java.io.Serializable;
> import java.util.ArrayList;
> import java.util.Comparator;
> import java.util.List;
> 
> import org.apache.commons.beanutils.BeanComparator;
> import org.apache.commons.collections.ComparatorUtils;
> import org.apache.commons.collections.comparators.NullComparator;
> import org.apache.commons.collections.comparators.ReverseComparator;
> import org.apache.commons.lang.StringUtils;
> 
> /**
>  * This comparator lets you sort a list using a list of properties. You
can specify ascending or
>  * descending order on these properties.
>  * <p>
>  * For example, if you want to sort with natural order a list of beans
with properties firstname,
>  * nickname and address, sorting the firstname descending, you can do it
this way:
>  * </p>
>  * <code>List l = ...</code>
>  * <code>...</code>
>  * <code>MultiPropertyBeanComparator multiPropBeanComp = new
MultiPropertyBeanComparator();</code>
>  * <code>multiPropBeanComp.append("firstname",
true).append("nickname").append("address");</code>
>  * <code>Collections.sort(l,multiPropBeanComp);</code>
>  * 
>  * @author Baptiste MATHUS
>  */
> public class MultiPropertyBeanComparator implements Comparator,
Serializable
> {
> 	private static final long serialVersionUID = -1431852774261001458L;
> 
> 	private List comparatorList = new ArrayList();
> 
> 	/**
> 	 * Use this method to add a comparator to the list.
> 	 * 
> 	 * @param property
> 	 *            the property on which to apply the given comparator.
> 	 * @param comparator
> 	 *            the comparator to be added. If null, natural order
will be used.
> 	 * @param reverse
> 	 *            <p>
> 	 *            must be true if the given comparator must be used in
opposite order to sort. For
> 	 *            example, if the comparator is designed to sort in
ascending order, put this
> 	 *            parameter to <code>true</code> if you want descending
order.
> 	 *            </p>
> 	 *            <p>
> 	 *            If the comparator is null, then the reversed natural
order is used.
> 	 *            </p>
> 	 */
> 	public MultiPropertyBeanComparator append(String property,
Comparator comparator,
> 			boolean reverse)
> 	{
> 		if (StringUtils.isBlank(property))
> 		{
> 			throw new IllegalArgumentException("The given
property is blank");
> 		}
> 
> 		// If the comparator is null, then compare only on the given
property
> 		// with a natural sort.
> 		if (comparator == null)
> 		{
> 			comparator = new BeanComparator(property, new
NullComparator(false));
> 		}
> 		// Else : compare on the property, but with given
comparator.
> 		else
> 		{
> 			comparator = new BeanComparator(property,
comparator);
> 		}
> 		// Here, the comparator cannot be null anymore, so reverse
it if
> 		// necessary.
> 		if (reverse)
> 		{
> 			comparator = new ReverseComparator(comparator);
> 		}
> 
> 		comparatorList.add(comparator);
> 
> 		return this;
> 	}
> 
> 	public MultiPropertyBeanComparator append(String property,
Comparator c)
> 	{
> 		return append(property, c, false);
> 	}
> 
> 	public MultiPropertyBeanComparator append(String property)
> 	{
> 		return append(property, null, false);
> 	}
> 
> 	public MultiPropertyBeanComparator append(String property, boolean
reverse)
> 	{
> 		return append(property, null, reverse);
> 	}
> 
> 	/**
> 	 * Use this method to clear the
> 	 */
> 	public void clear()
> 	{
> 		comparatorList.clear();
> 	}
> 
> 	/**
> 	 * Considered to be equal when all properties and comparators equal.
> 	 * 
> 	 * @see java.lang.Object#equals(java.lang.Object)
> 	 * @overrides
> 	 */
> 	public boolean equals(Object obj)
> 	{
> 		MultiPropertyBeanComparator comp =
(MultiPropertyBeanComparator) obj;
> 
> 		if (this.comparatorList.size() !=
comp.comparatorList.size())
> 		{
> 			return false;
> 		}
> 
> 		for (int i = 0; i < comparatorList.size(); ++i)
> 		{
> 			if
(!this.comparatorList.get(i).equals(comp.comparatorList.get(i)))
> 			{
> 				return false;
> 			}
> 		}
> 		return true;
> 	}
> 
> 	/**
> 	 * @see Comparator#compare(T, T)
> 	 * @overrides
> 	 */
> 	public int compare(Object arg0, Object arg1)
> 	{
> 		return getComparator().compare(arg0, arg1);
> 	}
> 
> 	private Comparator getComparator()
> 	{
> 		return ComparatorUtils.chainedComparator(comparatorList);
> 	}
> }
> =======================================
> 
> Thanks for the answers.
> 
> Baptiste
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-user-help@jakarta.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-user-help@jakarta.apache.org


Mime
View raw message