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);
}
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;
}
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);
}
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);
}
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);
}
Aggregations