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]