use of org.apache.commons.jexl2.JexlArithmetic in project commons-jexl by apache.
the class Interpreter method processAnnotation.
/**
* Processes an annotated statement.
* @param stmt the statement
* @param index the index of the current annotation being processed
* @param data the contextual data
* @return the result of the statement block evaluation
*/
protected Object processAnnotation(final ASTAnnotatedStatement stmt, final int index, final Object data) {
// are we evaluating the block ?
final int last = stmt.jjtGetNumChildren() - 1;
if (index == last) {
final JexlNode cblock = stmt.jjtGetChild(last);
// if the context has changed, might need a new interpreter
final JexlArithmetic jexla = arithmetic.options(context);
if (jexla == arithmetic) {
return cblock.jjtAccept(Interpreter.this, data);
}
if (!arithmetic.getClass().equals(jexla.getClass()) && logger.isWarnEnabled()) {
logger.warn("expected arithmetic to be " + arithmetic.getClass().getSimpleName() + ", got " + jexla.getClass().getSimpleName());
}
final Interpreter ii = new Interpreter(Interpreter.this, jexla);
final Object r = cblock.jjtAccept(ii, data);
if (ii.isCancelled()) {
Interpreter.this.cancel();
}
return r;
}
// tracking whether we processed the annotation
final AnnotatedCall jstmt = new AnnotatedCall(stmt, index + 1, data);
// the annotation node and name
final ASTAnnotation anode = (ASTAnnotation) stmt.jjtGetChild(index);
final String aname = anode.getName();
// evaluate the arguments
final Object[] argv = anode.jjtGetNumChildren() > 0 ? visit((ASTArguments) anode.jjtGetChild(0), null) : null;
// wrap the future, will recurse through annotation processor
Object result;
try {
result = processAnnotation(aname, argv, jstmt);
// not processing an annotation is an error
if (!jstmt.isProcessed()) {
return annotationError(anode, aname, null);
}
} catch (final JexlException xany) {
throw xany;
} catch (final Exception xany) {
return annotationError(anode, aname, xany);
}
// the caller may return a return, break or continue
if (result instanceof JexlException) {
throw (JexlException) result;
}
return result;
}
use of org.apache.commons.jexl2.JexlArithmetic in project commons-jexl by apache.
the class Uberspect method getArithmetic.
@Override
public JexlArithmetic.Uberspect getArithmetic(final JexlArithmetic arithmetic) {
JexlArithmetic.Uberspect jau = null;
if (arithmetic != null) {
final Class<? extends JexlArithmetic> aclass = arithmetic.getClass();
Set<JexlOperator> ops = operatorMap.get(aclass);
if (ops == null) {
ops = EnumSet.noneOf(JexlOperator.class);
// deal only with derived classes
if (!JexlArithmetic.class.equals(aclass)) {
for (final JexlOperator op : JexlOperator.values()) {
final Method[] methods = getMethods(arithmetic.getClass(), op.getMethodName());
if (methods != null) {
mloop: for (final Method method : methods) {
final Class<?>[] parms = method.getParameterTypes();
if (parms.length != op.getArity()) {
continue;
}
// - nor overridden (not present in base class)
if (!JexlArithmetic.class.equals(method.getDeclaringClass())) {
try {
JexlArithmetic.class.getMethod(method.getName(), method.getParameterTypes());
} catch (final NoSuchMethodException xmethod) {
// method was not found in JexlArithmetic; this is an operator definition
ops.add(op);
}
}
}
}
}
}
// register this arithmetic class in the operator map
operatorMap.put(aclass, ops);
}
jau = new ArithmeticUberspect(arithmetic, ops);
}
return jau;
}
use of org.apache.commons.jexl2.JexlArithmetic in project commons-jexl by apache.
the class Operators method empty.
/**
* Check for emptyness of various types: Collection, Array, Map, String, and anything that has a boolean isEmpty()
* method.
* <p>Note that the result may not be a boolean.
*
* @param node the node holding the object
* @param object the object to check the emptyness of
* @return the evaluation result
*/
protected Object empty(final JexlNode node, final Object object) {
if (object == null) {
return true;
}
Object result = tryOverload(node, JexlOperator.EMPTY, object);
if (result != JexlEngine.TRY_FAILED) {
return result;
}
final JexlArithmetic arithmetic = interpreter.arithmetic;
result = arithmetic.isEmpty(object, null);
if (result == null) {
final JexlUberspect uberspect = interpreter.uberspect;
result = false;
// check if there is an isEmpty method on the object that returns a
// boolean and if so, just use it
final JexlMethod vm = uberspect.getMethod(object, "isEmpty", Interpreter.EMPTY_PARAMS);
if (returnsBoolean(vm)) {
try {
result = vm.invoke(object, Interpreter.EMPTY_PARAMS);
} catch (final Exception xany) {
interpreter.operatorError(node, JexlOperator.EMPTY, xany);
}
}
}
return !(result instanceof Boolean) || (Boolean) result;
}
use of org.apache.commons.jexl2.JexlArithmetic in project commons-jexl by apache.
the class Operators method endsWith.
/**
* The 'endsWith' operator implementation.
* @param node the node
* @param operator the calling operator, ^= or ^!
* @param left the left operand
* @param right the right operand
* @return true if left ends with right, false otherwise
*/
protected boolean endsWith(final JexlNode node, final String operator, final Object left, final Object right) {
final JexlArithmetic arithmetic = interpreter.arithmetic;
final JexlUberspect uberspect = interpreter.uberspect;
try {
// try operator overload
final Object result = tryOverload(node, JexlOperator.ENDSWITH, left, right);
if (result instanceof Boolean) {
return (Boolean) result;
}
// use arithmetic / pattern matching ?
final Boolean matched = arithmetic.endsWith(left, right);
if (matched != null) {
return matched;
}
// try a endsWith method (duck type)
try {
final Object[] argv = { right };
JexlMethod vm = uberspect.getMethod(left, "endsWith", argv);
if (returnsBoolean(vm)) {
return (Boolean) vm.invoke(left, argv);
}
if (arithmetic.narrowArguments(argv)) {
vm = uberspect.getMethod(left, "endsWith", argv);
if (returnsBoolean(vm)) {
return (Boolean) vm.invoke(left, argv);
}
}
} catch (final Exception e) {
throw new JexlException(node, operator + " error", e);
}
// defaults to equal
return arithmetic.equals(left, right);
} catch (final ArithmeticException xrt) {
throw new JexlException(node, operator + " error", xrt);
}
}
use of org.apache.commons.jexl2.JexlArithmetic in project commons-jexl by apache.
the class Operators method size.
/**
* Calculate the <code>size</code> of various types:
* Collection, Array, Map, String, and anything that has a int size() method.
* <p>Note that the result may not be an integer.
*
* @param node the node that gave the value to size
* @param object the object to get the size of
* @return the evaluation result
*/
protected Object size(final JexlNode node, final Object object) {
if (object == null) {
return 0;
}
Object result = tryOverload(node, JexlOperator.SIZE, object);
if (result != JexlEngine.TRY_FAILED) {
return result;
}
final JexlArithmetic arithmetic = interpreter.arithmetic;
result = arithmetic.size(object, null);
if (result == null) {
final JexlUberspect uberspect = interpreter.uberspect;
// check if there is a size method on the object that returns an
// integer and if so, just use it
final JexlMethod vm = uberspect.getMethod(object, "size", Interpreter.EMPTY_PARAMS);
if (returnsInteger(vm)) {
try {
result = vm.invoke(object, Interpreter.EMPTY_PARAMS);
} catch (final Exception xany) {
interpreter.operatorError(node, JexlOperator.SIZE, xany);
}
}
}
return result instanceof Number ? ((Number) result).intValue() : 0;
}
Aggregations