/**
* Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.expression;
import javax.el.ELContext;
import javax.el.ELException;
import javax.el.ELResolver;
import javax.el.FunctionMapper;
import javax.el.PropertyNotFoundException;
import javax.el.ValueExpression;
import javax.el.VariableMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Function;
import com.opengamma.util.tuple.Pair;
import de.odysseus.el.util.SimpleResolver;
/**
* Representation of an EL expression.
*/
/* package */class ELExpression extends UserExpression {
private static final Logger s_logger = LoggerFactory.getLogger(ELExpression.class);
private final ELExpressionParser _parser;
private final ValueExpression _expr;
public ELExpression(final ELExpressionParser parser, final ValueExpression expr) {
_parser = parser;
_expr = expr;
}
/**
* Returns the original parser.
*
* @return the parser
*/
protected ELExpressionParser getParser() {
return _parser;
}
protected ValueExpression getExpr() {
return _expr;
}
private static final class Context extends ELContext {
private final ELResolver _resolver;
private final FunctionMapper _functionMapper;
private final VariableMapper _variableMapper;
public Context(final ELResolver resolver, final FunctionMapper functionMapper, final VariableMapper variableMapper) {
_resolver = resolver;
_functionMapper = functionMapper;
_variableMapper = variableMapper;
}
@Override
public ELResolver getELResolver() {
return _resolver;
}
@Override
public FunctionMapper getFunctionMapper() {
return _functionMapper;
}
@Override
public VariableMapper getVariableMapper() {
return _variableMapper;
}
}
/**
* Extends the parse context with evaluation state for an evaluation context.
*
* @return the context
*/
@Override
protected Object createContext(final Evaluator evaluator) {
final SimpleResolver resolver = new SimpleResolver(true) {
@Override
public Object getValue(final ELContext context, final Object base, final Object property) {
if (base == null) {
context.setPropertyResolved(true);
final Object value = evaluator.evaluateVariable((String) property);
if (value == NA) {
throw new PropertyNotFoundException("Variable " + property + " not defined");
} else {
return value;
}
} else if (property instanceof String) {
final Pair<Class<?>, Function<Object, Object>> synthetic = getParser().getSynthetic(base, (String) property);
if (synthetic != null) {
context.setPropertyResolved(true);
return synthetic.getSecond().apply(base);
} else {
Object value = super.getValue(context, base, property);
if (!context.isPropertyResolved()) {
value = evaluator.evaluateAttribute(base, (String) property);
if (value != NA) {
context.setPropertyResolved(true);
}
}
return value;
}
} else {
return super.getValue(context, base, property);
}
}
@Override
public Class<?> getType(final ELContext context, final Object base, final Object property) {
if (base == null) {
context.setPropertyResolved(true);
final Object value = evaluator.evaluateVariable((String) property);
if (value == NA) {
throw new PropertyNotFoundException("Variable " + property + " not defined");
} else {
return value.getClass();
}
} else if (property instanceof String) {
final Pair<Class<?>, Function<Object, Object>> synthetic = getParser().getSynthetic(base, (String) property);
if (synthetic != null) {
context.setPropertyResolved(true);
return synthetic.getFirst();
} else {
Class<?> type = super.getType(context, base, property);
if (!context.isPropertyResolved()) {
final Object value = evaluator.evaluateAttribute(base, (String) property);
if (value != NA) {
context.setPropertyResolved(true);
type = value.getClass();
}
}
return type;
}
} else {
return super.getType(context, base, property);
}
}
};
return new Context(resolver, null, null);
}
@Override
protected Object evaluate(final Evaluator evaluator) {
try {
return getExpr().getValue((ELContext) getContext(evaluator));
} catch (PropertyNotFoundException e) {
s_logger.debug("Property not found - {}", e.getMessage());
} catch (ELException e) {
s_logger.warn("EL exception", e);
}
return NA;
}
@Override
public String toString() {
return _expr.getExpressionString();
}
}