package nl.ipo.cds.validation.operators;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
import nl.ipo.cds.validation.AbstractExpression;
import nl.ipo.cds.validation.BinaryExpression;
import nl.ipo.cds.validation.Expression;
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 abstract class AbstractOperator<K extends Enum<K> & ValidationMessage<K, C>, C extends ValidatorContext<K, C>, ResultType, InputType> extends AbstractExpression<K, C, ResultType> implements BinaryExpression<K, C, ResultType, InputType, InputType> {
public final Expression<K, C, InputType> a;
public final Expression<K, C, InputType> b;
public AbstractOperator (final Expression<K, C, InputType> a, final Expression<K, C, InputType> b) {
if (a == null) {
throw new NullPointerException ("a cannot be null");
}
if (b == null) {
throw new NullPointerException ("b cannot be null");
}
this.a = a;
this.b = b;
}
public ResultType evaluate (final C context, final InputType a, final InputType b) {
final InputType aValue = a;
final InputType bValue = b;
if (aValue == null || bValue == null) {
throw new ExpressionEvaluationException (String.format ("Null values not accepted as input for %s", getClass ().getCanonicalName ()));
}
return evaluate (aValue, bValue, context);
}
public abstract ResultType evaluate (final InputType a, final InputType b, final C context);
public abstract String getOperatorName ();
@Override
public Class<InputType> getTypeA () {
return a.getResultType ();
}
@Override
public Class<InputType> getTypeB () {
return b.getResultType ();
}
@Override
public String toString () {
return String.format ("(%s %s %s)", a.toString (), getOperatorName (), b.toString ());
}
private final static MethodHandle evaluateHandle = Compiler
.findMethod (
AbstractOperator.class,
"evaluate",
MethodType.methodType (Object.class, ValidatorContext.class, Object.class, Object.class)
);
@Override
public ExpressionExecutor<C> getExecutor (final Compiler<C> compiler) throws CompilerException {
return ExpressionExecutor.create (
this,
a,
b,
false,
true,
evaluateHandle.bindTo (this),
false
);
}
}