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