Search in sources :

Example 1 with JexlPropertySet

use of org.apache.commons.jexl3.introspection.JexlPropertySet in project commons-jexl by apache.

the class InterpreterBase method setAttribute.

/**
 * Sets an attribute of an object.
 *
 * @param object    to set the value to
 * @param attribute the attribute of the object, e.g. an index (1, 0, 2) or key for a map
 * @param value     the value to assign to the object's attribute
 * @param node      the node that evaluated as the object
 */
protected void setAttribute(final Object object, final Object attribute, final Object value, final JexlNode node) {
    cancelCheck(node);
    final JexlOperator operator = node != null && node.jjtGetParent() instanceof ASTArrayAccess ? JexlOperator.ARRAY_SET : JexlOperator.PROPERTY_SET;
    final Object result = operators.tryOverload(node, operator, object, attribute, value);
    if (result != JexlEngine.TRY_FAILED) {
        return;
    }
    Exception xcause = null;
    try {
        // attempt to reuse last executor cached in volatile JexlNode.value
        if (node != null && cache) {
            final Object cached = node.jjtGetValue();
            if (cached instanceof JexlPropertySet) {
                final JexlPropertySet setter = (JexlPropertySet) cached;
                final Object eval = setter.tryInvoke(object, attribute, value);
                if (!setter.tryFailed(eval)) {
                    return;
                }
            }
        }
        final List<JexlUberspect.PropertyResolver> resolvers = uberspect.getResolvers(operator, object);
        JexlPropertySet vs = uberspect.getPropertySet(resolvers, object, attribute, value);
        // if we can't find an exact match, narrow the value argument and try again
        if (vs == null) {
            // replace all numbers with the smallest type that will fit
            final Object[] narrow = { value };
            if (arithmetic.narrowArguments(narrow)) {
                vs = uberspect.getPropertySet(resolvers, object, attribute, narrow[0]);
            }
        }
        if (vs != null) {
            // cache executor in volatile JexlNode.value
            vs.invoke(object, value);
            if (node != null && cache && vs.isCacheable()) {
                node.jjtSetValue(vs);
            }
            return;
        }
    } catch (final Exception xany) {
        xcause = xany;
    }
    // lets fail
    if (node == null) {
        // direct call
        final String error = "unable to set object property" + ", class: " + object.getClass().getName() + ", property: " + attribute + ", argument: " + value.getClass().getSimpleName();
        throw new UnsupportedOperationException(error, xcause);
    }
    final String attrStr = attribute != null ? attribute.toString() : null;
    unsolvableProperty(node, attrStr, true, xcause);
}
Also used : JexlPropertySet(org.apache.commons.jexl3.introspection.JexlPropertySet) JexlOperator(org.apache.commons.jexl3.JexlOperator) ASTArrayAccess(org.apache.commons.jexl3.parser.ASTArrayAccess) JexlException(org.apache.commons.jexl3.JexlException)

Example 2 with JexlPropertySet

use of org.apache.commons.jexl3.introspection.JexlPropertySet in project commons-jexl by apache.

the class Uberspect method getPropertySet.

@Override
public JexlPropertySet getPropertySet(final List<PropertyResolver> resolvers, final Object obj, final Object identifier, final Object arg) {
    final Class<?> claz = obj.getClass();
    final String property = AbstractExecutor.castString(identifier);
    final Introspector is = base();
    final List<PropertyResolver> actual = resolvers == null ? strategy.apply(null, obj) : resolvers;
    JexlPropertySet executor = null;
    for (final PropertyResolver resolver : actual) {
        if (resolver instanceof JexlResolver) {
            switch((JexlResolver) resolver) {
                case PROPERTY:
                    // first try for a setFoo() type of property (also setfoo() )
                    executor = PropertySetExecutor.discover(is, claz, property, arg);
                    break;
                case MAP:
                    // let's see if we are a map...
                    executor = MapSetExecutor.discover(is, claz, identifier, arg);
                    break;
                case LIST:
                    // let's see if we can convert the identifier to an int,
                    // if obj is an array or a list, we can still do something
                    final Integer index = AbstractExecutor.castInteger(identifier);
                    if (index != null) {
                        executor = ListSetExecutor.discover(is, claz, identifier, arg);
                    }
                    break;
                case DUCK:
                    // if that didn't work, look for set(foo)
                    executor = DuckSetExecutor.discover(is, claz, identifier, arg);
                    if (executor == null && property != null && property != identifier) {
                        executor = DuckSetExecutor.discover(is, claz, property, arg);
                    }
                    break;
                case FIELD:
                    // a field may be?
                    executor = FieldSetExecutor.discover(is, claz, property, arg);
                    break;
                case CONTAINER:
                default:
                    // in case we add new ones in enum
                    continue;
            }
        } else {
            executor = resolver.getPropertySet(this, obj, identifier, arg);
        }
        if (executor != null) {
            return executor;
        }
    }
    return null;
}
Also used : JexlPropertySet(org.apache.commons.jexl3.introspection.JexlPropertySet) AtomicInteger(java.util.concurrent.atomic.AtomicInteger)

Example 3 with JexlPropertySet

use of org.apache.commons.jexl3.introspection.JexlPropertySet in project commons-jexl by apache.

the class ReferenceUberspect method getPropertySet.

@Override
public JexlPropertySet getPropertySet(List<PropertyResolver> resolvers, Object ref, Object identifier, Object arg) {
    // is this is a reference of some kind?
    ReferenceHandler handler = discoverHandler(ref);
    if (handler == null) {
        return uberspect.getPropertySet(resolvers, ref, identifier, arg);
    }
    // do we have an object referenced ?
    Object obj = handler.callGet(ref);
    if (ref == obj) {
        return null;
    }
    // from that object, get the property setter if any
    JexlPropertySet jexlSet = null;
    if (obj != null) {
        jexlSet = uberspect.getPropertySet(resolvers, obj, identifier, arg);
        if (jexlSet == null) {
            throw new JexlException.Property(null, Objects.toString(identifier), false, null);
        }
    } else {
        // postpone resolution till not null
        jexlSet = new OptionalNullSetter(uberspect, identifier);
    }
    return new ReferenceSetExecutor(handler, jexlSet);
}
Also used : JexlPropertySet(org.apache.commons.jexl3.introspection.JexlPropertySet)

Example 4 with JexlPropertySet

use of org.apache.commons.jexl3.introspection.JexlPropertySet in project commons-jexl by apache.

the class StrategyTest method testRawResolvers.

@Test
public void testRawResolvers() throws Exception {
    final Object map = new HashMap<String, Object>();
    final JexlEngine jexl = new JexlBuilder().create();
    final JexlUberspect uberspect = jexl.getUberspect();
    final JexlUberspect.PropertyResolver rfieldp = JexlUberspect.JexlResolver.FIELD;
    final JexlPropertyGet fget = rfieldp.getPropertyGet(uberspect, map, "key");
    Assert.assertNull(fget);
    final JexlPropertySet fset = rfieldp.getPropertySet(uberspect, map, "key", "value");
    Assert.assertNull(fset);
    final JexlUberspect.PropertyResolver rmap = JexlUberspect.JexlResolver.MAP;
    final JexlPropertyGet mget = rmap.getPropertyGet(uberspect, map, "key");
    Assert.assertNotNull(mget);
    final JexlPropertySet mset = rmap.getPropertySet(uberspect, map, "key", "value");
    Assert.assertNotNull(mset);
}
Also used : JexlPropertySet(org.apache.commons.jexl3.introspection.JexlPropertySet) HashMap(java.util.HashMap) JexlUberspect(org.apache.commons.jexl3.introspection.JexlUberspect) JexlPropertyGet(org.apache.commons.jexl3.introspection.JexlPropertyGet) Test(org.junit.Test)

Example 5 with JexlPropertySet

use of org.apache.commons.jexl3.introspection.JexlPropertySet in project commons-jexl by apache.

the class MethodTest method testTryFailed.

@Test
public void testTryFailed() throws Exception {
    // JEXL-257
    final Functor func = new Functor();
    final JexlContext ctxt = new MapContext();
    ctxt.set("func", func);
    Object result;
    final JexlUberspect uber = JEXL.getUberspect();
    // tryInvoke
    final JexlMethod method = uber.getMethod(func, "over", "foo", 42);
    Assert.assertNotNull(method);
    // tryInvoke succeeds
    result = method.tryInvoke("over", func, "foo", 42);
    Assert.assertEquals("foo + 42", result);
    // tryInvoke fails
    func.setKill(true);
    try {
        /*result = */
        method.tryInvoke("over", func, "foo", 42);
        Assert.fail("should throw TryFailed");
    } catch (final JexlException.TryFailed xfail) {
        Assert.assertEquals(UnsupportedOperationException.class, xfail.getCause().getClass());
    }
    func.setKill(false);
    final JexlPropertySet setter = uber.getPropertySet(func, "under", "42");
    result = setter.tryInvoke(func, "under", "42");
    Assert.assertFalse(setter.tryFailed(result));
    Assert.assertEquals("42", result);
    final JexlPropertyGet getter = uber.getPropertyGet(func, "under");
    result = getter.tryInvoke(func, "under");
    Assert.assertFalse(getter.tryFailed(result));
    Assert.assertEquals("42", result);
    func.setKill(true);
    try {
        /*result = */
        setter.tryInvoke(func, "under", "42");
        Assert.fail("should throw TryFailed");
    } catch (final JexlException.TryFailed xfail) {
        Assert.assertEquals(UnsupportedOperationException.class, xfail.getCause().getClass());
    }
    func.setKill(false);
    result = setter.tryInvoke(func, "under", "-42");
    Assert.assertEquals("-42", result);
    func.setKill(true);
    try {
        /*result = */
        getter.tryInvoke(func, "under");
        Assert.fail("should throw TryFailed");
    } catch (final JexlException.TryFailed xfail) {
        Assert.assertEquals(UnsupportedOperationException.class, xfail.getCause().getClass());
    }
    func.setKill(false);
    result = getter.tryInvoke(func, "under");
    Assert.assertFalse(getter.tryFailed(result));
    Assert.assertEquals("-42", result);
}
Also used : JexlPropertySet(org.apache.commons.jexl3.introspection.JexlPropertySet) JexlMethod(org.apache.commons.jexl3.introspection.JexlMethod) JexlUberspect(org.apache.commons.jexl3.introspection.JexlUberspect) JexlPropertyGet(org.apache.commons.jexl3.introspection.JexlPropertyGet) Test(org.junit.Test)

Aggregations

JexlPropertySet (org.apache.commons.jexl3.introspection.JexlPropertySet)9 Test (org.junit.Test)7 JexlPropertyGet (org.apache.commons.jexl3.introspection.JexlPropertyGet)6 JexlUberspect (org.apache.commons.jexl3.introspection.JexlUberspect)3 HashMap (java.util.HashMap)2 ArrayList (java.util.ArrayList)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1 JexlException (org.apache.commons.jexl3.JexlException)1 JexlOperator (org.apache.commons.jexl3.JexlOperator)1 JexlMethod (org.apache.commons.jexl3.introspection.JexlMethod)1 ASTArrayAccess (org.apache.commons.jexl3.parser.ASTArrayAccess)1