/**
* Copyright (c) 2013-2016, The SeedStack authors <http://seedstack.org>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.seedstack.seed.core.internal.el;
import com.google.common.base.Strings;
import org.seedstack.seed.SeedException;
import org.seedstack.seed.el.ELService;
import javax.el.ELContext;
import javax.el.ELException;
import javax.el.ExpressionFactory;
import javax.el.MethodExpression;
import javax.el.PropertyNotFoundException;
import javax.el.ValueExpression;
import javax.inject.Inject;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Implementation of ELService.
*/
class ELServiceInternal implements ELService {
@Inject
private ExpressionFactory expressionFactory;
@Override
public ELContextProvider withExpression(String el, Class returnType) {
checkArgument(!Strings.isNullOrEmpty(el), "An expression is required");
checkNotNull(returnType, "The return type must not be null");
return new ELInstance(expressionFactory, el, returnType);
}
@Override
public ValueExpressionProvider withValueExpression(ValueExpression valueExpression) {
checkNotNull(valueExpression, "The value expression must not be null");
ELInstance elInstance = new ELInstance(expressionFactory);
elInstance.setValueExpression(valueExpression);
return elInstance;
}
@Override
public MethodExpressionProvider withMethodExpression(MethodExpression methodExpression) {
checkNotNull(methodExpression, "The method expression must not be null");
ELInstance elInstance = new ELInstance(expressionFactory);
elInstance.setMethodExpression(methodExpression);
return elInstance;
}
private static class ELInstance implements ELContextProvider, ELExpressionProvider, ELService.MethodExpressionProvider, ELService.ValueExpressionProvider {
private final ExpressionFactory expressionFactory;
private String el;
private Class returnType;
private MethodExpression methodExpression;
private ValueExpression valueExpression;
private ELContext context;
ELInstance(ExpressionFactory expressionFactory) {
this.expressionFactory = expressionFactory;
}
ELInstance(ExpressionFactory expressionFactory, String el, Class returnType) {
this.expressionFactory = expressionFactory;
this.el = el;
this.returnType = returnType;
}
@Override
public ELExpressionProvider withContext(ELContext elContext) {
checkNotNull(elContext, "The context must not be null");
context = elContext;
return this;
}
@Override
public ELExpressionProvider withDefaultContext() {
context = ELContextBuilderImpl.createDefaultELContext(expressionFactory);
return this;
}
@Override
public ValueExpression valueExpression() {
return valueExpression;
}
@Override
public ValueExpressionProvider asValueExpression() {
valueExpression = expressionFactory.createValueExpression(context, el, returnType);
return this;
}
@Override
public MethodExpression methodExpression() {
return methodExpression;
}
@Override
public MethodExpressionProvider asMethodExpression(Class<?>[] expectedParamTypes) {
methodExpression = expressionFactory.createMethodExpression(context, el, returnType, expectedParamTypes);
return this;
}
@Override
public Object eval() {
Object value;
try {
value = valueExpression.getValue(context);
} catch (PropertyNotFoundException e) {
throw SeedException.wrap(e, ExpressionLanguageErrorCode.PROPERTY_NOT_FOUND).put("el", el);
} catch (ELException e) {
throw SeedException.wrap(e, ExpressionLanguageErrorCode.EL_EXCEPTION).put("el", el);
}
return value;
}
@Override
public Object invoke(Object[] args) {
Object value;
try {
value = methodExpression.invoke(context, args);
} catch (PropertyNotFoundException e) {
throw SeedException.wrap(e, ExpressionLanguageErrorCode.PROPERTY_NOT_FOUND).put("el", el);
} catch (ELException e) {
throw SeedException.wrap(e, ExpressionLanguageErrorCode.EL_EXCEPTION).put("el", el);
}
return value;
}
void setMethodExpression(MethodExpression methodExpression) {
this.methodExpression = methodExpression;
}
void setValueExpression(ValueExpression valueExpression) {
this.valueExpression = valueExpression;
}
}
}