-新Validationプラン

。。。ということで、出来たみたい。ValidatorもConvertorもPOJOでいけるなあ。

public interface NewValidationAPI {
    @Retention(RUNTIME)
    @Target({METHOD})
    public @interface Variable {
    }

    @Retention(RUNTIME)
    @Target({METHOD})
    public @interface Execute {
    }

    @Retention(RUNTIME)
    @Target({ANNOTATION_TYPE})
    public @interface Validator {
        Class delegateTo();
    }
}
public interface MyValidation {
    @Retention(RUNTIME)
    @Target({METHOD})
    @Validator(delegateTo=LengthValidatorImpl.class)
    public @interface LengthValidator {
        int min() default -1;
        int max() default -1;
    }

    public class LengthValidatorImpl {
        private int _min = -1;
        private int _max = -1;
        @Variable
        public void setMin(int min) {
            _min = min;
        }
        @Variable
        public void setMax(int max) {
            _max = max;
        }
        @Execute
        public void validate(String value) throws Throwable {
            if(value == null) {
                new Throwable("null");
            }
            int len = value.length();
            if(_min != -1 && len < _min) {
                throw new Throwable("min");
            }
            if(_max != -1 && _max < len) {
                throw new Throwable("max");
            }
        }
    }
}
public class NewValidationRunTest extends TestCase {
    public void testRun() throws Throwable {
        //++ lazy initialization.
        final Class pageModel = ValidationTestRunModel.class;
        final Method method = pageModel.getMethod("setName", String.class);
        final String value = "1234";
        //--
        Annotation userValidatorInstance = null;
        for(Annotation annotation: method.getAnnotations()) {
            if(annotation.annotationType().isAnnotationPresent(Validator.class)) {
                userValidatorInstance = annotation;
                break;
            }
        }
        if(userValidatorInstance != null) {
            Class userValidator =
                userValidatorInstance.annotationType();
            Validator validator = userValidator.getAnnotation(Validator.class);
            Class delegateTo = validator.delegateTo();
            Method delegateMethod = null;
            for(Method execute: delegateTo.getMethods()) {
                if(execute.isAnnotationPresent(Execute.class)) {
                    delegateMethod = execute;
                    break;
                }
            }
            if(delegateMethod == null) {
                throw new IllegalStateException();
            }
            try {
                Object validatorImpl = delegateTo.newInstance();
                //++ lazy reflection
                Method setMax = delegateTo.getMethod("setMax", int.class);
                Method max = userValidator.getMethod("max");
                setMax.invoke(validatorImpl, max.invoke(userValidatorInstance));
                //--
                delegateMethod.invoke(validatorImpl, value);
            } catch(InvocationTargetException t) {
                String msg = t.getTargetException().getMessage();
                assertEquals("max", msg);
                return;
            }
        }
        fail();
    }
}