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.ExpressionEvaluationException;
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 CallbackExpression<K extends Enum<K> & ValidationMessage<K, C>, C extends ValidatorContext<K, C>, T> extends AbstractExpression<K, C, T> {
public final Class<T> type;
public final Callback<K, C, T> callback;
public final String label;
public CallbackExpression (final Class<T> type, final Callback<K, C, T> callback) {
this (type, callback, null);
}
public CallbackExpression (final Class<T> type, final Callback<K, C, T> callback, final String label) {
if (type == null) {
throw new NullPointerException ("type cannot be null");
}
if (callback == null) {
throw new NullPointerException ("callback cannot be null");
}
this.type = type;
this.callback = callback;
this.label = label;
}
public CallbackExpression<K, C, T> label (final String label) {
return new CallbackExpression<K, C, T> (type, callback, label);
}
@Override
public Class<T> getResultType () {
return type;
}
public T evaluate (final C context) {
try {
return callback.call (context);
} catch (Exception e) {
throw new ExpressionEvaluationException (e);
}
}
private final static MethodHandle evaluateHandle = Compiler
.findMethod (
Callback.class,
"call",
MethodType.methodType (Object.class, ValidatorContext.class)
);
@Override
public ExpressionExecutor<C> getExecutor(final Compiler<C> compiler) throws CompilerException {
return ExpressionExecutor.create (
this,
false,
false,
evaluateHandle.bindTo (callback),
false
);
}
}