JochenW
JochenW

Reputation: 1053

JEXL: How to customize property accessors

I've got data objects, which you could think of as a "simplified map". There are methods get(String), and put(String,Object), but that's basically it.

Now, I'd like to use JEXL to evaluate complex expressions on my data objects. I can do so by creating a custom JexlContext, and that works for expressions like "foo", or foo != null. However, as soon as I attempt to use an expression like "foo.bar", Jexl fails with an error message "unsolvable property". Obviously, Jexl uses my custom JexlContext to evaluate "foo", but can't evaluate "bar" on the foo object. My impression is, that I've got to use a custom PropertyResolver. I can implement that, but I can't figure out. how to bring that into the game, as the JexlUberspect doesn't contain a method like setResolvers, or addResolver.

Upvotes: 0

Views: 1263

Answers (1)

tkruse
tkruse

Reputation: 10695

Similar to the duplicate question, I guess you can do:

public class ExtendedJexlArithmetic extends JexlArithmetic
{
    public Object propertyGet(YourCustomClass left, YourCustomClass right)
    {
       // ...
    }
}

JexlEngine jexlEngine=new JexlBuilder().arithmetic(new ExtendedJexlArithmetic (true)).create();
// or
JexlEngine jexl = new JexlEngine(null, new ExtendedJexlArithmetic(), null, null);

From the documentation at: https://commons.apache.org/proper/commons-jexl/apidocs/org/apache/commons/jexl3/package-summary.html

You can also add methods to overload property getters and setters operators behaviors. Public methods of the JexlArithmetic instance named propertyGet/propertySet/arrayGet/arraySet are potential overrides that will be called when appropriate. The following table is an overview of the relation between a syntactic form and the method to call where V is the property value class, O the object class and P the property identifier class (usually String or Integer).

Expression                   Method Template
foo.property              public V propertyGet(O obj, P property);

foo.property = value      public V propertySet(O obj, P property, V value);

foo[property]             public V arrayGet(O obj, P property, V value);

foo[property] = value     public V arraySet(O obj, P property, V value);

Upvotes: 1

Related Questions