package nl.ipo.cds.validation.callbacks;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
import nl.ipo.cds.validation.AbstractExpression;
import nl.ipo.cds.validation.Expression;
import nl.ipo.cds.validation.ExpressionEvaluationException;
import nl.ipo.cds.validation.UnaryExpression;
import nl.ipo.cds.validation.ValidationMessage;
import nl.ipo.cds.validation.ValidatorContext;
import nl.ipo.cds.validation.execute.Compiler;
import nl.ipo.cds.validation.execute.CompilerException;
import nl.ipo.cds.validation.execute.ExpressionExecutor;
public class UnaryCallbackExpression<K extends Enum<K> & ValidationMessage<K, C>, C extends ValidatorContext<K, C>, ResultType, InputType> extends AbstractExpression<K, C, ResultType> implements UnaryExpression<K, C, ResultType, InputType> {
public final Class<ResultType> resultType;
public final Expression<K, C, InputType> input;
public final UnaryCallback<K, C, ResultType, InputType> callback;
public final String label;
public UnaryCallbackExpression (final Class<ResultType> resultType, final Expression<K, C, InputType> inputExpression, final UnaryCallback<K, C, ResultType, InputType> callback) {
this (resultType, inputExpression, callback, null);
}
public UnaryCallbackExpression (final Class<ResultType> resultType, final Expression<K, C, InputType> inputExpression, final UnaryCallback<K, C, ResultType, InputType> callback, final String label) {
if (resultType == null) {
throw new NullPointerException ("resultType cannot be null");
}
if (inputExpression == null) {
throw new NullPointerException ("inputExpression cannot be null");
}
if (callback == null) {
throw new NullPointerException ("callback cannot be null");
}
this.resultType = resultType;
this.input = inputExpression;
this.callback = callback;
this.label = label;
}
public UnaryCallbackExpression<K, C, ResultType, InputType> label (final String label) {
return new UnaryCallbackExpression<K, C, ResultType, InputType> (resultType, input, callback, label);
}
@Override
public Class<ResultType> getResultType () {
return resultType;
}
public ResultType evaluate (final C context, final InputType input) {
final InputType inputValue = input;
try {
return callback.call (inputValue, context);
} catch (Exception e) {
throw new ExpressionEvaluationException (e);
}
}
@Override
public Class<InputType> getInputType() {
return input.getResultType ();
}
private final static MethodHandle evaluateHandle = Compiler
.findMethod (
UnaryCallbackExpression.class,
"evaluate",
MethodType.methodType (Object.class, ValidatorContext.class, Object.class)
);
@Override
public ExpressionExecutor<C> getExecutor(final Compiler<C> compiler) throws CompilerException {
return ExpressionExecutor.create (
this,
input,
false,
false,
evaluateHandle.bindTo (this),
false
);
}
}