Valang Validator under the hood

Table of Contents

1. Valang Validator under the hood
1.1. How to Convert Valang syntax Expression into ValidationRule Object model? 1.2. Custom ValangValidator or ValidationRule

1. Valang Validator under the hood

1.1. How to Convert Valang syntax Expression into ValidationRule Object model?

org.springmodules.validation.valang.parser.ValangParser is the key class that will help on this task.

If you are able to construct a valid valang-syntax expression from some other sources, you can use ValangParser to parse these kinds of expressions into Valang's Object model. for example:

Errors errors = ...;
Object target = ...;
				
ValangParser parser = new ValangParser("{ <key> : <expression> : <error_message> [ : <error_key> [ : <error_args> ] ]}");
try {
    Collection<ValidationRule> rules = parser.parseValidation();
    if(CollectionUtils.isNotEmpty(rules))
    {
        Iterator<ValidationRule> iter = rules.iterator();
        while(iter.hasNext()){
            ValidationRule rule = iter.next();
            rule.validate(target, errors);
        }
    }
} catch (ParseException e) {
	// handle exception here.
}
 				

with sample code above, I think you can figure out how the ValangValidator class do its work.

Since you can “setValang(String valang) ”, you can “setCustomFunctions(..) ”, in the “validate(Object target, Errors errors) ” method, the ValangValidator only need use ValangParser to parse the expression set via “setValang(String) ” method. After a collection of ValidationRule is available, the left things is almost the same like code above.

Of course, since ValangValidator use ValangParser to do the parsing things, you can use ValangValidator or its super class, that's, org.springmodules.validation.valang.parser.SimpleValangBased , to do the same thing. I mean, to parse the valang expression.

1.2. Custom ValangValidator or ValidationRule

when I want to add GlobalError support for ROMA framework, I found that as if Valang doesn't support such GlobalError expression things, so I have to find another way.

In a valang-syntax expression, the first token is the <key>, it's mandatory. But for a global error, it's meaningless. so even we provide a dummy <key> value, and make the expression-parsing pass, when we invoke the “#validate(target, errors) ” method of ValidationRule, an exception will still be raised, because, the ValidationRule can't find a property on the target object. In order to fix this, we have to break down the “#validate(target, errors) ” method's logic. Here is what I will do.

If we inspect the type of the ValidationRule returned from “parser.parseValidation() ”, we will find that it's type is org.springmodules.validation.valang.predicates.BasicValidationRule . This is the default value object that hold every part of the parsed Valang expression. Since we can get everything with it, we then can filter the returned collection of ValidationRule. The code seems like:

ValangValidator validator = new ValangValidator();
        validator.setValang("");
        @SuppressWarnings("unchecked")
        Collection<ValidationRule> rules = validator.getRules();
        @SuppressWarnings("unchecked")
        Collection<ValidationRule> globalErrorRules = CollectionUtils.transformedCollection(rules, new Transformer() {
            public Object transform(Object arg) {
                final BasicValidationRule rule = (BasicValidationRule)arg;
                return new ValidationRule() {
                    public void validate(Object target, org.springframework.validation.Errors errors) {
                        String errorKey = rule.getErrorKey();
                        String message = rule.getErrorMessage();
                        @SuppressWarnings("unchecked")
                        Collection args = rule.getErrorArgs();
                        if(CollectionUtils.isEmpty(args))
                        {
                            errors.reject(errorKey, message);
                        }
                        else
                        {
                            @SuppressWarnings("unchecked")
                            Object[] argArray = args.toArray(new Object[args.size()]);
                            errors.reject(errorKey, argArray, message);
                        }
                    }
                };
            }
        });
 

since FiledError is added with “#rejectValue(..) ”, we use “#reject(..) ” to fill GlobalError to Errors . After these rules are applied to the target object, the corresponding global errors will be available. You can pull them in you view via spring's RequestContext or other way you resort to.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值