JBEL - Java Boolean Expression Library SourceForge.net Logo
Project summary on Source Forge.
Download from Source Forge

JBEL is a small, efficient Java library enabling programmers to create simple, easily understandable expressions to perform collection filtering and/or sorting. It also supports the concept of closures to facilitate rapid implementation of filtering and sorting functionality. The following benefits are realized through consistent use of JBEL:
  • No more copy-n-paste coding for comparing and filtering.
  • Reduce duplicated code and code size.
  • Improve filter and sort clarity, readability, and maintainability.
  • Increase application reliability with reduced bug introduction.
  • Utilize closure (see wikipedia) concepts in your Java code.
The following examples should get you going on your understanding and justification for use of JBEL. After a look, the benefits are obvious, especially when considering the amount of copy-n-paste coding that often happens around comparing and filtering. For additional examples, check out the unit tests in the source code (available at SourceForge).

Filtering

Before JBEL:

After JBEL:

private Collection filterCollection(Collection toFilter)
{
  Collection results = new Vector();
  Iterator iterator = toFilter.iterator();

  while (iterator.hasNext())
  {
    (SomeInstance) instance = (SomeInstance) iterator.next();

    if (instance.getAccountBalance() > 10000
        && instance.isNewCustomer())
    {
      results.add(instance);
    }
  }

  return results;
}

Collection results = filterCollection(toFilter);
			
SelectExpressionBuilder builder = CollectionUtils.newSelectExpressionBuilder();
builder.attribute("accountBalance").greaterThan(10000)
  .and(builder.attribute("isNewCustomer").equalTo(true));

Collection results = CollectionUtils.select(toFilter, builder.getExpression());
Or we could use closure-style functionality instead of the builder above...
Collection results = CollectionUtils.select(toFilter, new AbstractPredicate()
  {
    public boolean test(Object argument)
    throws EvaluationException
    {
      Customer customer = (Customer) argument;
      return (customer.getAccountBalance() > 10000.0
        && customer.isNewCustomer());
    }
  }
);

Sorting/Collation

Before JBEL:

After JBEL:

public class PersonNameComparator
implements Comparator
{
  public int compare(Object obj1, Object obj2)
  {
    Person person1 = (Person) obj1;
    Person person2 = (Person) obj2;
    int result = person1.getLastName()
      .compareTo(person2.getLastName());

    if (result == 0)
    {
      result = person1.getFirstName()
        .compareTo(person2.getFirstName());
    }

    if (result == 0)
    {
      result = person1.getMiddleInitial()
        .compareTo(person2.getMiddleInitial());
    }

    return result;
  }
}

Collections.sort(peopleToSort, new PersonNameComparator());
CollationExpressionBuilder
orderBy = CollectionUtils.newCollationExpressionBuilder();
orderBy.attribute("lastName")
  .attribute("firstName")
  .attribute("middleInitial");

Collections.sort(peopleToSort, orderBy.getExpression());
Or, call Collections.sort() indirectly by simply evaluating the expression...
orderBy.evaluate(peopleToSort);
		  

Closures

The concept of closures is a functional programming concept. Essentially, a JBEL closure is an object that can be passed around and is supported by the interfaces, Expression, UnaryFunction, BinaryFunction, and Predicate.

You can read more about closures on wikipedia.

Here is an example of a closure utilized within JBEL to support the CollectionUtils.select() operation.

private static class SelectFunction
implements UnaryFunction
{
	Predicate predicate;
	Collection results;
	
	public SelectFunction(Predicate predicate, Collection resultingCollection)
	{
		this.predicate = predicate;
		this.results = resultingCollection;
	}
	
	@Override
	public Object perform(Object argument)
	throws FunctionException
	{
		if (isSelected(argument))
		{
			results.add((T) argument);
		}
		
		return null;
	}

	protected boolean isSelected(Object argument)
	throws FunctionException
	{
		try
		{
			return predicate.test(argument);
		}
		catch (EvaluationException e)
		{
			throw new FunctionException(e);
		}
	}

	public Collection getResults()
	{
		return results;
	}
}

SelectFunction selectFunction = new SelectFunction(predicate, newCollectionOfType(collection));
for (Object element : collection)
{
	selectFunction.perform(element);
}
return selectFunction.getResults();