package com.github.overengineer.scope.conversation.expression.eval;
import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.mvel2.MVEL;
import org.mvel2.ParserContext;
import org.mvel2.compiler.ExpressionCompiler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.overengineer.scope.conversation.ConversationAdapter;
import com.github.overengineer.scope.conversation.ConversationUtil;
import com.github.overengineer.scope.conversation.expression.exceptions.ExpressionEvaluationException;
/**
* @author reesbyars
*/
public class Mvel implements Eval {
private static final Logger LOG = LoggerFactory.getLogger(Mvel.class);
private final Map<String, Serializable> templateCache = new ConcurrentHashMap<String, Serializable>();
private final ParserContext context;
public Mvel() {
context = new ParserContext();
try {
context.addImport("get", ConversationUtil.class.getMethod("getContextUsingSimpleName", String.class));
context.addImport("begin", ConversationUtil.class.getMethod("beginUsingSimpleName", new Class<?>[]{String.class, long.class, int.class}));
context.addImport("end", ConversationUtil.class.getMethod("endUsingSimpleName", String.class));
context.addImport("continue", ConversationUtil.class.getMethod("persistUsingSimpleName", String.class));
} catch (SecurityException e) {
LOG.error("Could not instantiate expression parsing context. Evaluation of @Eval expressions may be compromised.", e);
} catch (NoSuchMethodException e) {
LOG.error("Could not instantiate expression parsing context. Evaluation of @Eval expressions may be compromised.", e);
}
}
/**
* {@inheritDoc}
*/
@Override
public Object evaluate(String expression, Map<String, Object> evaluationContext, Object root) throws ExpressionEvaluationException {
try {
Serializable template = this.templateCache.get(expression);
if (template == null) {
LOG.debug("Compiled template not found in cache, compiling template and caching.");
ExpressionCompiler compiler = new ExpressionCompiler(expression);
compiler.newContext(context);
template = compiler.compile();
this.templateCache.put(expression, template);
}
return MVEL.executeExpression(template, root, evaluationContext);
} catch (Exception e) {
throw new ExpressionEvaluationException(expression, e);
}
}
/**
* {@inheritDoc}
*/
@Override
public Object evaluate(String expression) throws ExpressionEvaluationException {
try {
return this.evaluate(expression, ConversationAdapter.getAdapter().getActionContext(), ConversationAdapter.getAdapter().getAction());
} catch (Exception e) {
throw new ExpressionEvaluationException(expression, e);
}
}
}