A Filtered Sneak Peek Into a Sneak Peek

Henrik Paul
On Mar 17, 2011 12:43:00 PM

Our very own Henri Sara from the Vaadin development team held a presentation on something exciting: Filters! Well ok, filters by themselves aren't that exciting, but the improvements he came to show were indeed out of this world.

So, the way container filtering works today is by the addContainerFilter(Object, String, bool, bool) method in a Container.Filterable: You give the property id of the property you want to filter with, and a String that the property value should match when passed through toString(). Let me say that again: The property's value is converted into a String (be it a Date, Boolean or anything else), and the filtering is compared to the String you gave to the method. But there's more: if you add more filters into a container, they're all simply AND:ed together. No, there's no way to "OR" stuff together.

These are pretty big API blunders that we've carried on with us since back when we had IT Mill Toolkit 5.0(!). So that'll finally get fixed in 6.6.

The old addContainerFilter() method will get overloaded with a method that wants a single as an argument. This will allow you to filter your containers any way you like. You'll be able to filter in ways that were impractical, if not outright impossible to do before. Booleans? no problem. Date comparison? you got it.

Anyways. After Henri finished his presentation, I got excited, grabbed the latest nightly and started playing around. Doing the filter was indeed a breeze.

The Filter interface looks as follows:

public interface Filter extends Serializable {
  public boolean appliesToProperty(Object propertyId);
  public boolean passesFilter(Item item) 
      throws UnsupportedOperationException;

All very simple and basic stuff. The former method is a way to optimize the filtering process, while the latter one is the actual business end of the filter. Here's a contrived example I whipped up in a jiffy that shows only weekend entries in a Table, based on a java.util.Calendar-type property in the Table's IndexedContainer.

public boolean passesFilter(final Item item) 
                   throws UnsupportedOperationException {
  final Calendar cal = (Calendar) item
  final int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);

  return dayOfWeek == Calendar.SATURDAY ||
         dayOfWeek == Calendar.SUNDAY;

I have a hard time imagining an easier and more intuitive way to define custom filterings for your Collections.

The example above is pretty minimalistic and arbitrary. The example Henri showed in his presentation was much neater, not to mention more practical. He live-coded a new container in front of all of us which could filter out all points in a map outside of an irregular shape. Combining this with Google Maps, the user could draw a polygon and the points of interest inside that area only were shown. All thanks to the new filter API. It's impossible to do that so neatly with the old API.

One thing I know for sure that once 6.6.0 gets finalized and released: I'll stop doing any kind of funky custom manual server-side in-memory filterings on my containers to generate containers with only a subset (sounds familiar?), and instead start using the filters directly …now that they'll get actually usable for values other than String, and all.

A word of warning: everything I've played aroud with here is from one of the earliest 6.6.0 nightlies, and 6.6 is not due for another 8 weeks. Everything might still change before 6.6.0 comes out. But do check it out, since it'll only get better, if anything, before launch. Not to mention, this is just one of the many changes coming to 6.6.

Henrik Paul
Henrik Paul works as a Scrum Master at Vaadin's product development. He has been working at Vaadin since 2008 with basically anything and everything, except in sales or administration. He's one of those annoying guys who is never satisfied with the status quo, and questions established practices constantly.
Other posts by Henrik Paul