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.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 class BinaryCallbackExpression<K extends Enum<K> & ValidationMessage<K, C>, C extends ValidatorContext<K, C>, ResultType, TypeA, TypeB> extends AbstractExpression<K, C, ResultType> implements BinaryExpression<K, C, ResultType, TypeA, TypeB> { public final Class<ResultType> resultType; public final Expression<K, C, TypeA> a; public final Expression<K, C, TypeB> b; public final BinaryCallback<K, C, ResultType, TypeA, TypeB> callback; public final String label; public BinaryCallbackExpression (final Class<ResultType> resultType, final Expression<K, C, TypeA> a, final Expression<K, C, TypeB> b, final BinaryCallback<K, C, ResultType, TypeA, TypeB> callback) { this (resultType, a, b, callback, null); } public BinaryCallbackExpression (final Class<ResultType> resultType, final Expression<K, C, TypeA> a, final Expression<K, C, TypeB> b, final BinaryCallback<K, C, ResultType, TypeA, TypeB> callback, final String label) { if (resultType == null) { throw new NullPointerException ("resultType cannot be null"); } if (a == null || b == null) { throw new NullPointerException ("inputs cannot be null"); } if (callback == null) { throw new NullPointerException ("callback cannot be null"); } this.resultType = resultType; this.a = a; this.b = b; this.callback = callback; this.label = label; } public ResultType evaluate (final C context, final TypeA a, final TypeB b) { try { return callback.call (a, b, context); } catch (Exception e) { throw new ExpressionEvaluationException (e); } } @Override public Class<ResultType> getResultType () { return resultType; } private final static MethodHandle evaluateHandle = Compiler .findMethod ( BinaryCallbackExpression.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, false, evaluateHandle.bindTo (this), false ); } @Override public Class<TypeA> getTypeA () { return a.getResultType (); } @Override public Class<TypeB> getTypeB () { return b.getResultType (); } }