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