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:[EMAIL PROTECTED] 
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("[EMAIL PROTECTED] >= 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: [EMAIL PROTECTED]
>For additional commands, e-mail: [EMAIL PROTECTED]
>
>
>
>
>  
>




---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to