JSR303 валидатор съобщение рекурсивна резолюция?

Написах JSR303 валидатор, който сравнява стойността на свойството с ограничението:

@Documented
@Constraint(validatedBy = Cmp.LongCmpValidator.class)
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
public @interface Cmp {
    String message() default "{home.lang.validator.Cmp.message}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
    long value();
    public enum REL { LT,LT_EQ,EQ,GT,GT_EQ;
        @Override
        public String toString() {
            return toString_property();
        }
        public String toString_property() {
            switch(this) {
                case LT   : return "{home.lang.validator.Cmp.REL.LT}";
                case LT_EQ: return "{home.lang.validator.Cmp.REL.LT_EQ}";
                case    EQ: return "{home.lang.validator.Cmp.REL.EQ}";
                case GT   : return "{home.lang.validator.Cmp.REL.GT}";
                case GT_EQ: return "{home.lang.validator.Cmp.REL.GT_EQ}";
            }
            throw new UnsupportedOperationException();
        }
        public String toString_common() { return super.toString(); }
        public String toString_math() { switch(this) {
                case LT   : return "<";
                case LT_EQ: return "\u2264";
                case    EQ: return "=";
                case GT   : return ">";
                case GT_EQ: return "\u2265";
            }
            throw new UnsupportedOperationException();
        }
    }
    REL prop_rel_cnstr();

    @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
    @Retention(RUNTIME)
    @Documented
    @interface List {
        Cmp[] value();
    }

    class LongCmpValidator implements ConstraintValidator<Cmp, Number> {
        long cnstr_val;
        REL prop_rel_cnstr;

        public void initialize(Cmp constraintAnnotation) {
            cnstr_val = constraintAnnotation.value();
            prop_rel_cnstr = constraintAnnotation.prop_rel_cnstr();
        }

        public boolean isValid(Number _value, ConstraintValidatorContext context) {
            if(_value == null) return true;

            if(_value instanceof Integer) {
                int value = _value.intValue();
                switch(prop_rel_cnstr) {
                    case LT   : return value <  cnstr_val;
                    case LT_EQ: return value <= cnstr_val;
                    case    EQ: return value == cnstr_val;
                    case GT   : return value >  cnstr_val;
                    case GT_EQ: return value >= cnstr_val;
                }
            }
            // ... handle other types
            return true;
        }
    }
}

ValidationMessages.properties:

home.lang.validator.Cmp.REL.LT=less than
home.lang.validator.Cmp.REL.LT_EQ=less than or equal
home.lang.validator.Cmp.REL.EQ=equal
home.lang.validator.Cmp.REL.GT=greater
home.lang.validator.Cmp.REL.GT_EQ=greater than or equal

home.lang.validator.Cmp.message=Failure: validated value is to be in relation "{prop_rel_cnstr}" to {value}.

Работи добре. почти. Съобщението за проверка, което получавам, изглежда така:

Failure: validated value is to be in relation "{home.lang.validator.Cmp.REL.GT}" to 0.

Някой би ли предложил лесен и удобен начин как да накарам Validator да разпознава и разрешава вложен ключ {home.lang.validator.Cmp.REL.GT}? Имам нужда да бъде добре използваем в JSF2, който обработва валидирането. Не използвам Spring, но използвам hibernate-validator 4.

Между другото, изглежда, че hibernate-validator 4 не прилага напълно JSR303, тъй като по-късните състояния в 4.3.1.1.:

  1. Параметрите на съобщението се извличат от низа на съобщението и се използват като ключове за търсене в ResourceBundle с име ValidationMessages (често материализирани като файл със свойства /ValidationMessages.properties и неговите вариации на локал) с помощта на дефинирания локал (вижте по-долу). Ако бъде намерено свойство, параметърът на съобщението се заменя със стойността на свойството в низа на съобщението. Стъпка 1 се прилага рекурсивно, докато не бъде извършена замяна (т.е. стойността на параметър на съобщение може сама по себе си да съдържа параметър на съобщение).

person Andrey    schedule 20.04.2011    source източник


Отговори (1)


Добре, разрових се в това. Алгоритъмът, определен от JSR303, има неинтуитивна бъркотия с това какво (реквизити) са рекурсивно разрешими и какво не. Мисля, че това се дължи главно на лошото разграничение в граматиката на свойствата на анотацията и свойствата на RB.

Така че направих свой собствен MessageInterpolator, който можете да намерите в моето репо: http://github.com/Andrey-Sisoyev/adv-msg-interpolator. Той решава почти всички проблеми, а също така позволява да се обърне внимание на пакета от ресурси, къде да търсите имота.

person Andrey    schedule 23.04.2011