commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Poppe, Troy" <Troy.Po...@eia.doe.gov>
Subject RE: Expressions, Collections, Filtering oh my..
Date Wed, 06 Jul 2005 14:04:34 GMT

I actually ended up doing something like this, Tim.  Thanks for your help.  I did
one thing slightly different, and that was to use PropertyUtils.describe(Object)
to get a Map of JavaBean properties for populating the JexlContext... See below
as a first cut:

<-- snip -->

package a.b.com;

import java.util.Map;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.collections.Predicate;
import org.apache.commons.jexl.Expression;
import org.apache.commons.jexl.ExpressionFactory;
import org.apache.commons.jexl.JexlContext;
import org.apache.commons.jexl.JexlHelper;

public class JexlPredicate implements Predicate
{
	public String expression = null;

	public boolean evaluate(Object o)
	{
		boolean ret = false;
		
		try
		{
			Map objectMap = PropertyUtils.describe(o);
			Expression e =
ExpressionFactory.createExpression(expression);
			JexlContext jc = JexlHelper.createContext();
			jc.setVars(objectMap);
			
			Object eval = e.evaluate(jc);
			if ( eval != null && eval instanceof Boolean )
			{
				ret = ((Boolean)eval).booleanValue(); 
			}
		}
		catch ( Exception ex )
		{
			throw new RuntimeException(ex);
		}
		
		return ret;
	}

	public String getExpression()
	{
		return expression;
	}

	public void setExpression(String expression)
	{
		this.expression = expression;
	}
}

<-- snip -->

-----Original Message-----
From: Tim O'Brien [mailto:tobrien@discursive.com] 
Sent: Tuesday, July 05, 2005 9:13 PM
To: Jakarta Commons Users List
Subject: Re: Expressions, Collections, Filtering oh my..


Here are two ways to do this, JXPath is easier as you won't have to 
write your own Predicate.

Say you have a collection of Person objects that you created with this code:

        Person person1 = new Person();
        person1.setName( "Bill" );
        person1.setAge( 12 );

        Person person2 = new Person();
        person2.setName( "Amy" );
        person2.setAge( 18 );

        Person person3 = new Person();
        person3.setName( "Doug" );
        person3.setAge( 25 );

        List personList =
            Arrays.asList( new Person[] { person1, person2, person3 } );

You can filter this collection using JXPath and an XPath expression that 
references the age property AS IF it were an XML attribute:

        JXPathContext context = JXPathContext.newContext( personList );
        Iterator iterator = context.iterate(".[@age >= 18]");
        while( iterator.hasNext() ) {
            Object o  = (Object) iterator.next();
            System.out.println( "Person: " + ((Person) o).getName());
        }

Or, you can write a custom JexlPredicate that takes an expression and 
evaluates each element in a Collection.  Here's code that filters a 
collection of Person beans and returns only those instances that have an 
age >= 18:

       Predicate predicate = new JexlPredicate( "object", "object.age >= 
18" );
      
       Collection canVote = CollectionUtils.select( personList, predicate );
       
        for( Object o : canVote ) {
            System.out.println( "Person: " + ((Person) o).getName() );
        }

The JexlPredicate from this example would be the following class:

<JexlPredicate.java>

import org.apache.commons.collections.Predicate;
import org.apache.commons.jexl.Expression;
import org.apache.commons.jexl.ExpressionFactory;
import org.apache.commons.jexl.JexlContext;
import org.apache.commons.jexl.JexlHelper;

public class JexlPredicate implements Predicate {

    private String variable;
    private Expression e;

    public JexlPredicate(String variable, String expression) {
        this.variable = variable;
        try {
            this.e = ExpressionFactory.createExpression(expression);
        } catch (Exception e) {
            throw new RuntimeException("Error creating JEXL expression", e);
        }
    }

    public boolean evaluate(Object o) {
        JexlContext jc = JexlHelper.createContext();
        jc.getVars().put(variable, o);
       
        Boolean b;
        try {
            b = (Boolean) e.evaluate(jc);
        } catch (Exception e) {
            throw new RuntimeException("Error evaluating JEXL 
expression", e);
        }
        return b.booleanValue();
    }

}

</JexlPredicate.java>

Poppe, Troy wrote:

>I've got a collection of a JavaBeans, it could be a plain-old-Java 
>collection or a Commons-Collection... Not really a concern...
>
>I'm trying to find a way to provide the ability to write a JEXL-like 
>expression that would be applied against the collection of JavaBeans, 
>and be able to retrieve all of the JavaBeans that match that JEXL-like 
>expression.
>
>So far, looking at JEXL, it looks like it requires a JexlContext, but I 
>don't see or know how I would adapt my JavaBean properties to this.
>
>Is there an out-of-the-binary way of filtering through my JavaBeans, 
>and giving me access to those that match some expression?
>
>Thanks.
>
>Troy
>
>
>---------------------------------------------------------------------
>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



---------------------------------------------------------------------
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