001/*
002 * Copyright 2002-2014 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.validation;
018
019import org.apache.commons.logging.Log;
020import org.apache.commons.logging.LogFactory;
021
022import org.springframework.util.Assert;
023import org.springframework.util.ObjectUtils;
024import org.springframework.util.StringUtils;
025
026/**
027 * Utility class offering convenient methods for invoking a {@link Validator}
028 * and for rejecting empty fields.
029 *
030 * <p>Checks for an empty field in {@code Validator} implementations can become
031 * one-liners when using {@link #rejectIfEmpty} or {@link #rejectIfEmptyOrWhitespace}.
032 *
033 * @author Juergen Hoeller
034 * @author Dmitriy Kopylenko
035 * @since 06.05.2003
036 * @see Validator
037 * @see Errors
038 */
039public abstract class ValidationUtils {
040
041        private static final Log logger = LogFactory.getLog(ValidationUtils.class);
042
043
044        /**
045         * Invoke the given {@link Validator} for the supplied object and
046         * {@link Errors} instance.
047         * @param validator the {@code Validator} to be invoked (must not be {@code null})
048         * @param obj the object to bind the parameters to
049         * @param errors the {@link Errors} instance that should store the errors (must not be {@code null})
050         * @throws IllegalArgumentException if either of the {@code Validator} or {@code Errors} arguments is
051         * {@code null}, or if the supplied {@code Validator} does not {@link Validator#supports(Class) support}
052         * the validation of the supplied object's type
053         */
054        public static void invokeValidator(Validator validator, Object obj, Errors errors) {
055                invokeValidator(validator, obj, errors, (Object[]) null);
056        }
057
058        /**
059         * Invoke the given {@link Validator}/{@link SmartValidator} for the supplied object and
060         * {@link Errors} instance.
061         * @param validator the {@code Validator} to be invoked (must not be {@code null})
062         * @param obj the object to bind the parameters to
063         * @param errors the {@link Errors} instance that should store the errors (must not be {@code null})
064         * @param validationHints one or more hint objects to be passed to the validation engine
065         * @throws IllegalArgumentException if either of the {@code Validator} or {@code Errors} arguments is
066         * {@code null}, or if the supplied {@code Validator} does not {@link Validator#supports(Class) support}
067         * the validation of the supplied object's type
068         */
069        public static void invokeValidator(Validator validator, Object obj, Errors errors, Object... validationHints) {
070                Assert.notNull(validator, "Validator must not be null");
071                Assert.notNull(errors, "Errors object must not be null");
072                if (logger.isDebugEnabled()) {
073                        logger.debug("Invoking validator [" + validator + "]");
074                }
075                if (obj != null && !validator.supports(obj.getClass())) {
076                        throw new IllegalArgumentException(
077                                        "Validator [" + validator.getClass() + "] does not support [" + obj.getClass() + "]");
078                }
079                if (!ObjectUtils.isEmpty(validationHints) && validator instanceof SmartValidator) {
080                        ((SmartValidator) validator).validate(obj, errors, validationHints);
081                }
082                else {
083                        validator.validate(obj, errors);
084                }
085                if (logger.isDebugEnabled()) {
086                        if (errors.hasErrors()) {
087                                logger.debug("Validator found " + errors.getErrorCount() + " errors");
088                        }
089                        else {
090                                logger.debug("Validator found no errors");
091                        }
092                }
093        }
094
095
096        /**
097         * Reject the given field with the given error code if the value is empty.
098         * <p>An 'empty' value in this context means either {@code null} or
099         * the empty string "".
100         * <p>The object whose field is being validated does not need to be passed
101         * in because the {@link Errors} instance can resolve field values by itself
102         * (it will usually hold an internal reference to the target object).
103         * @param errors the {@code Errors} instance to register errors on
104         * @param field the field name to check
105         * @param errorCode the error code, interpretable as message key
106         */
107        public static void rejectIfEmpty(Errors errors, String field, String errorCode) {
108                rejectIfEmpty(errors, field, errorCode, null, null);
109        }
110
111        /**
112         * Reject the given field with the given error code and default message
113         * if the value is empty.
114         * <p>An 'empty' value in this context means either {@code null} or
115         * the empty string "".
116         * <p>The object whose field is being validated does not need to be passed
117         * in because the {@link Errors} instance can resolve field values by itself
118         * (it will usually hold an internal reference to the target object).
119         * @param errors the {@code Errors} instance to register errors on
120         * @param field the field name to check
121         * @param errorCode error code, interpretable as message key
122         * @param defaultMessage fallback default message
123         */
124        public static void rejectIfEmpty(Errors errors, String field, String errorCode, String defaultMessage) {
125                rejectIfEmpty(errors, field, errorCode, null, defaultMessage);
126        }
127
128        /**
129         * Reject the given field with the given error code and error arguments
130         * if the value is empty.
131         * <p>An 'empty' value in this context means either {@code null} or
132         * the empty string "".
133         * <p>The object whose field is being validated does not need to be passed
134         * in because the {@link Errors} instance can resolve field values by itself
135         * (it will usually hold an internal reference to the target object).
136         * @param errors the {@code Errors} instance to register errors on
137         * @param field the field name to check
138         * @param errorCode the error code, interpretable as message key
139         * @param errorArgs the error arguments, for argument binding via MessageFormat
140         * (can be {@code null})
141         */
142        public static void rejectIfEmpty(Errors errors, String field, String errorCode, Object[] errorArgs) {
143                rejectIfEmpty(errors, field, errorCode, errorArgs, null);
144        }
145
146        /**
147         * Reject the given field with the given error code, error arguments
148         * and default message if the value is empty.
149         * <p>An 'empty' value in this context means either {@code null} or
150         * the empty string "".
151         * <p>The object whose field is being validated does not need to be passed
152         * in because the {@link Errors} instance can resolve field values by itself
153         * (it will usually hold an internal reference to the target object).
154         * @param errors the {@code Errors} instance to register errors on
155         * @param field the field name to check
156         * @param errorCode the error code, interpretable as message key
157         * @param errorArgs the error arguments, for argument binding via MessageFormat
158         * (can be {@code null})
159         * @param defaultMessage fallback default message
160         */
161        public static void rejectIfEmpty(
162                        Errors errors, String field, String errorCode, Object[] errorArgs, String defaultMessage) {
163
164                Assert.notNull(errors, "Errors object must not be null");
165                Object value = errors.getFieldValue(field);
166                if (value == null || !StringUtils.hasLength(value.toString())) {
167                        errors.rejectValue(field, errorCode, errorArgs, defaultMessage);
168                }
169        }
170
171        /**
172         * Reject the given field with the given error code if the value is empty
173         * or just contains whitespace.
174         * <p>An 'empty' value in this context means either {@code null},
175         * the empty string "", or consisting wholly of whitespace.
176         * <p>The object whose field is being validated does not need to be passed
177         * in because the {@link Errors} instance can resolve field values by itself
178         * (it will usually hold an internal reference to the target object).
179         * @param errors the {@code Errors} instance to register errors on
180         * @param field the field name to check
181         * @param errorCode the error code, interpretable as message key
182         */
183        public static void rejectIfEmptyOrWhitespace(Errors errors, String field, String errorCode) {
184                rejectIfEmptyOrWhitespace(errors, field, errorCode, null, null);
185        }
186
187        /**
188         * Reject the given field with the given error code and default message
189         * if the value is empty or just contains whitespace.
190         * <p>An 'empty' value in this context means either {@code null},
191         * the empty string "", or consisting wholly of whitespace.
192         * <p>The object whose field is being validated does not need to be passed
193         * in because the {@link Errors} instance can resolve field values by itself
194         * (it will usually hold an internal reference to the target object).
195         * @param errors the {@code Errors} instance to register errors on
196         * @param field the field name to check
197         * @param errorCode the error code, interpretable as message key
198         * @param defaultMessage fallback default message
199         */
200        public static void rejectIfEmptyOrWhitespace(
201                        Errors errors, String field, String errorCode, String defaultMessage) {
202
203                rejectIfEmptyOrWhitespace(errors, field, errorCode, null, defaultMessage);
204        }
205
206        /**
207         * Reject the given field with the given error code and error arguments
208         * if the value is empty or just contains whitespace.
209         * <p>An 'empty' value in this context means either {@code null},
210         * the empty string "", or consisting wholly of whitespace.
211         * <p>The object whose field is being validated does not need to be passed
212         * in because the {@link Errors} instance can resolve field values by itself
213         * (it will usually hold an internal reference to the target object).
214         * @param errors the {@code Errors} instance to register errors on
215         * @param field the field name to check
216         * @param errorCode the error code, interpretable as message key
217         * @param errorArgs the error arguments, for argument binding via MessageFormat
218         * (can be {@code null})
219         */
220        public static void rejectIfEmptyOrWhitespace(
221                        Errors errors, String field, String errorCode, Object[] errorArgs) {
222
223                rejectIfEmptyOrWhitespace(errors, field, errorCode, errorArgs, null);
224        }
225
226        /**
227         * Reject the given field with the given error code, error arguments
228         * and default message if the value is empty or just contains whitespace.
229         * <p>An 'empty' value in this context means either {@code null},
230         * the empty string "", or consisting wholly of whitespace.
231         * <p>The object whose field is being validated does not need to be passed
232         * in because the {@link Errors} instance can resolve field values by itself
233         * (it will usually hold an internal reference to the target object).
234         * @param errors the {@code Errors} instance to register errors on
235         * @param field the field name to check
236         * @param errorCode the error code, interpretable as message key
237         * @param errorArgs the error arguments, for argument binding via MessageFormat
238         * (can be {@code null})
239         * @param defaultMessage fallback default message
240         */
241        public static void rejectIfEmptyOrWhitespace(
242                        Errors errors, String field, String errorCode, Object[] errorArgs, String defaultMessage) {
243
244                Assert.notNull(errors, "Errors object must not be null");
245                Object value = errors.getFieldValue(field);
246                if (value == null ||!StringUtils.hasText(value.toString())) {
247                        errors.rejectValue(field, errorCode, errorArgs, defaultMessage);
248                }
249        }
250
251}