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 java.util.List; 020 021import org.springframework.beans.PropertyAccessor; 022import org.springframework.lang.Nullable; 023 024/** 025 * Stores and exposes information about data-binding and validation 026 * errors for a specific object. 027 * 028 * <p>Field names can be properties of the target object (e.g. "name" 029 * when binding to a customer object), or nested fields in case of 030 * subobjects (e.g. "address.street"). Supports subtree navigation 031 * via {@link #setNestedPath(String)}: for example, an 032 * {@code AddressValidator} validates "address", not being aware 033 * that this is a subobject of customer. 034 * 035 * <p>Note: {@code Errors} objects are single-threaded. 036 * 037 * @author Rod Johnson 038 * @author Juergen Hoeller 039 * @see #setNestedPath 040 * @see BindException 041 * @see DataBinder 042 * @see ValidationUtils 043 */ 044public interface Errors { 045 046 /** 047 * The separator between path elements in a nested path, 048 * for example in "customer.name" or "customer.address.street". 049 * <p>"." = same as the 050 * {@link org.springframework.beans.PropertyAccessor#NESTED_PROPERTY_SEPARATOR nested property separator} 051 * in the beans package. 052 */ 053 String NESTED_PATH_SEPARATOR = PropertyAccessor.NESTED_PROPERTY_SEPARATOR; 054 055 056 /** 057 * Return the name of the bound root object. 058 */ 059 String getObjectName(); 060 061 /** 062 * Allow context to be changed so that standard validators can validate 063 * subtrees. Reject calls prepend the given path to the field names. 064 * <p>For example, an address validator could validate the subobject 065 * "address" of a customer object. 066 * @param nestedPath nested path within this object, 067 * e.g. "address" (defaults to "", {@code null} is also acceptable). 068 * Can end with a dot: both "address" and "address." are valid. 069 */ 070 void setNestedPath(String nestedPath); 071 072 /** 073 * Return the current nested path of this {@link Errors} object. 074 * <p>Returns a nested path with a dot, i.e. "address.", for easy 075 * building of concatenated paths. Default is an empty String. 076 */ 077 String getNestedPath(); 078 079 /** 080 * Push the given sub path onto the nested path stack. 081 * <p>A {@link #popNestedPath()} call will reset the original 082 * nested path before the corresponding 083 * {@code pushNestedPath(String)} call. 084 * <p>Using the nested path stack allows to set temporary nested paths 085 * for subobjects without having to worry about a temporary path holder. 086 * <p>For example: current path "spouse.", pushNestedPath("child") -> 087 * result path "spouse.child."; popNestedPath() -> "spouse." again. 088 * @param subPath the sub path to push onto the nested path stack 089 * @see #popNestedPath 090 */ 091 void pushNestedPath(String subPath); 092 093 /** 094 * Pop the former nested path from the nested path stack. 095 * @throws IllegalStateException if there is no former nested path on the stack 096 * @see #pushNestedPath 097 */ 098 void popNestedPath() throws IllegalStateException; 099 100 /** 101 * Register a global error for the entire target object, 102 * using the given error description. 103 * @param errorCode error code, interpretable as a message key 104 */ 105 void reject(String errorCode); 106 107 /** 108 * Register a global error for the entire target object, 109 * using the given error description. 110 * @param errorCode error code, interpretable as a message key 111 * @param defaultMessage fallback default message 112 */ 113 void reject(String errorCode, String defaultMessage); 114 115 /** 116 * Register a global error for the entire target object, 117 * using the given error description. 118 * @param errorCode error code, interpretable as a message key 119 * @param errorArgs error arguments, for argument binding via MessageFormat 120 * (can be {@code null}) 121 * @param defaultMessage fallback default message 122 */ 123 void reject(String errorCode, @Nullable Object[] errorArgs, @Nullable String defaultMessage); 124 125 /** 126 * Register a field error for the specified field of the current object 127 * (respecting the current nested path, if any), using the given error 128 * description. 129 * <p>The field name may be {@code null} or empty String to indicate 130 * the current object itself rather than a field of it. This may result 131 * in a corresponding field error within the nested object graph or a 132 * global error if the current object is the top object. 133 * @param field the field name (may be {@code null} or empty String) 134 * @param errorCode error code, interpretable as a message key 135 * @see #getNestedPath() 136 */ 137 void rejectValue(@Nullable String field, String errorCode); 138 139 /** 140 * Register a field error for the specified field of the current object 141 * (respecting the current nested path, if any), using the given error 142 * description. 143 * <p>The field name may be {@code null} or empty String to indicate 144 * the current object itself rather than a field of it. This may result 145 * in a corresponding field error within the nested object graph or a 146 * global error if the current object is the top object. 147 * @param field the field name (may be {@code null} or empty String) 148 * @param errorCode error code, interpretable as a message key 149 * @param defaultMessage fallback default message 150 * @see #getNestedPath() 151 */ 152 void rejectValue(@Nullable String field, String errorCode, String defaultMessage); 153 154 /** 155 * Register a field error for the specified field of the current object 156 * (respecting the current nested path, if any), using the given error 157 * description. 158 * <p>The field name may be {@code null} or empty String to indicate 159 * the current object itself rather than a field of it. This may result 160 * in a corresponding field error within the nested object graph or a 161 * global error if the current object is the top object. 162 * @param field the field name (may be {@code null} or empty String) 163 * @param errorCode error code, interpretable as a message key 164 * @param errorArgs error arguments, for argument binding via MessageFormat 165 * (can be {@code null}) 166 * @param defaultMessage fallback default message 167 * @see #getNestedPath() 168 */ 169 void rejectValue(@Nullable String field, String errorCode, 170 @Nullable Object[] errorArgs, @Nullable String defaultMessage); 171 172 /** 173 * Add all errors from the given {@code Errors} instance to this 174 * {@code Errors} instance. 175 * <p>This is a convenience method to avoid repeated {@code reject(..)} 176 * calls for merging an {@code Errors} instance into another 177 * {@code Errors} instance. 178 * <p>Note that the passed-in {@code Errors} instance is supposed 179 * to refer to the same target object, or at least contain compatible errors 180 * that apply to the target object of this {@code Errors} instance. 181 * @param errors the {@code Errors} instance to merge in 182 */ 183 void addAllErrors(Errors errors); 184 185 /** 186 * Return if there were any errors. 187 */ 188 boolean hasErrors(); 189 190 /** 191 * Return the total number of errors. 192 */ 193 int getErrorCount(); 194 195 /** 196 * Get all errors, both global and field ones. 197 * @return a list of {@link ObjectError} instances 198 */ 199 List<ObjectError> getAllErrors(); 200 201 /** 202 * Are there any global errors? 203 * @return {@code true} if there are any global errors 204 * @see #hasFieldErrors() 205 */ 206 boolean hasGlobalErrors(); 207 208 /** 209 * Return the number of global errors. 210 * @return the number of global errors 211 * @see #getFieldErrorCount() 212 */ 213 int getGlobalErrorCount(); 214 215 /** 216 * Get all global errors. 217 * @return a list of {@link ObjectError} instances 218 */ 219 List<ObjectError> getGlobalErrors(); 220 221 /** 222 * Get the <i>first</i> global error, if any. 223 * @return the global error, or {@code null} 224 */ 225 @Nullable 226 ObjectError getGlobalError(); 227 228 /** 229 * Are there any field errors? 230 * @return {@code true} if there are any errors associated with a field 231 * @see #hasGlobalErrors() 232 */ 233 boolean hasFieldErrors(); 234 235 /** 236 * Return the number of errors associated with a field. 237 * @return the number of errors associated with a field 238 * @see #getGlobalErrorCount() 239 */ 240 int getFieldErrorCount(); 241 242 /** 243 * Get all errors associated with a field. 244 * @return a List of {@link FieldError} instances 245 */ 246 List<FieldError> getFieldErrors(); 247 248 /** 249 * Get the <i>first</i> error associated with a field, if any. 250 * @return the field-specific error, or {@code null} 251 */ 252 @Nullable 253 FieldError getFieldError(); 254 255 /** 256 * Are there any errors associated with the given field? 257 * @param field the field name 258 * @return {@code true} if there were any errors associated with the given field 259 */ 260 boolean hasFieldErrors(String field); 261 262 /** 263 * Return the number of errors associated with the given field. 264 * @param field the field name 265 * @return the number of errors associated with the given field 266 */ 267 int getFieldErrorCount(String field); 268 269 /** 270 * Get all errors associated with the given field. 271 * <p>Implementations should support not only full field names like 272 * "name" but also pattern matches like "na*" or "address.*". 273 * @param field the field name 274 * @return a List of {@link FieldError} instances 275 */ 276 List<FieldError> getFieldErrors(String field); 277 278 /** 279 * Get the first error associated with the given field, if any. 280 * @param field the field name 281 * @return the field-specific error, or {@code null} 282 */ 283 @Nullable 284 FieldError getFieldError(String field); 285 286 /** 287 * Return the current value of the given field, either the current 288 * bean property value or a rejected update from the last binding. 289 * <p>Allows for convenient access to user-specified field values, 290 * even if there were type mismatches. 291 * @param field the field name 292 * @return the current value of the given field 293 */ 294 @Nullable 295 Object getFieldValue(String field); 296 297 /** 298 * Return the type of a given field. 299 * <p>Implementations should be able to determine the type even 300 * when the field value is {@code null}, for example from some 301 * associated descriptor. 302 * @param field the field name 303 * @return the type of the field, or {@code null} if not determinable 304 */ 305 @Nullable 306 Class<?> getFieldType(String field); 307 308}