package nl.ipo.cds.validation.logical; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; import java.util.ArrayList; import java.util.List; import nl.ipo.cds.validation.AbstractExpression; import nl.ipo.cds.validation.Expression; import nl.ipo.cds.validation.NAryExpression; 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.ExecutableExpression; import nl.ipo.cds.validation.execute.ExpressionExecutor; public abstract class AbstractLogicalNAryExpr<K extends Enum<K> & ValidationMessage<K, C>, C extends ValidatorContext<K, C>> extends AbstractExpression<K, C, Boolean> implements NAryExpression<K, C, Boolean, Boolean> { public final List<Expression<K, C, Boolean>> inputs; public AbstractLogicalNAryExpr (final List<Expression<K, C, Boolean>> expressions) { if (expressions.size () < 1) { throw new IllegalArgumentException ("must have at least one input"); } this.inputs = new ArrayList<Expression<K, C, Boolean>> (expressions); } @Override public Class<Boolean> getResultType () { return Boolean.class; } @Override public Class<Boolean> getInputType () { return Boolean.class; } public Boolean evaluate (final ValidatorContext<K, C> context, final Boolean ... inputs) { // Evaluate all inputs: final ArrayList<Boolean> results = new ArrayList<Boolean> (inputs.length); for (final Boolean input: inputs) { final Boolean result = input; results.add (result); } // Let the logical operator do the rest of the work: return evaluate (results); } public abstract boolean evaluate (final List<Boolean> inputValues); private final static MethodHandle evaluateHandle = Compiler .findMethod ( AbstractLogicalNAryExpr.class, "evaluate", MethodType.methodType (Boolean.class, ValidatorContext.class, Boolean[].class) ); @Override public ExpressionExecutor<C> getExecutor (final Compiler<C> compiler) throws CompilerException { final List<ExecutableExpression<C, ?>> inputs = new ArrayList<ExecutableExpression<C, ?>> (); for (final Expression<K, C, Boolean> input: this.inputs) { inputs.add (input); } return new ExpressionExecutor<C> ( this, inputs, false, true, evaluateHandle.bindTo (this), true ); } }