001: /*
002: * Copyright 2002-2006 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: * http://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:
017: package org.springframework.validation;
018:
019: import java.util.List;
020:
021: import 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</code> validates "address", not being aware
032: * that this is a subobject of customer.
033: *
034: * <p>Note: <code>Errors</code> 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: */
043: public 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: * Return the name of the bound root object.
056: */
057: String getObjectName();
058:
059: /**
060: * Allow context to be changed so that standard validators can validate
061: * subtrees. Reject calls prepend the given path to the field names.
062: * <p>For example, an address validator could validate the subobject
063: * "address" of a customer object.
064: * @param nestedPath nested path within this object,
065: * e.g. "address" (defaults to "", <code>null</code> is also acceptable).
066: * Can end with a dot: both "address" and "address." are valid.
067: */
068: void setNestedPath(String nestedPath);
069:
070: /**
071: * Return the current nested path of this {@link Errors} object.
072: * <p>Returns a nested path with a dot, i.e. "address.", for easy
073: * building of concatenated paths. Default is an empty String.
074: */
075: String getNestedPath();
076:
077: /**
078: * Push the given sub path onto the nested path stack.
079: * <p>A {@link #popNestedPath()} call will reset the original
080: * nested path before the corresponding
081: * <code>pushNestedPath(String)</code> call.
082: * <p>Using the nested path stack allows to set temporary nested paths
083: * for subobjects without having to worry about a temporary path holder.
084: * <p>For example: current path "spouse.", pushNestedPath("child") ->
085: * result path "spouse.child."; popNestedPath() -> "spouse." again.
086: * @param subPath the sub path to push onto the nested path stack
087: * @see #popNestedPath
088: */
089: void pushNestedPath(String subPath);
090:
091: /**
092: * Pop the former nested path from the nested path stack.
093: * @throws IllegalStateException if there is no former nested path on the stack
094: * @see #pushNestedPath
095: */
096: void popNestedPath() throws IllegalStateException;
097:
098: /**
099: * Register a global error for the entire target object,
100: * using the given error description.
101: * @param errorCode error code, interpretable as a message key
102: */
103: void reject(String errorCode);
104:
105: /**
106: * Register a global error for the entire target object,
107: * using the given error description.
108: * @param errorCode error code, interpretable as a message key
109: * @param defaultMessage fallback default message
110: */
111: void reject(String errorCode, String defaultMessage);
112:
113: /**
114: * Register a global error for the entire target object,
115: * using the given error description.
116: * @param errorCode error code, interpretable as a message key
117: * @param errorArgs error arguments, for argument binding via MessageFormat
118: * (can be <code>null</code>)
119: * @param defaultMessage fallback default message
120: */
121: void reject(String errorCode, Object[] errorArgs,
122: 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</code> 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</code> 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</code> 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</code> 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,
152: 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</code> 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</code> 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</code>)
166: * @param defaultMessage fallback default message
167: * @see #getNestedPath()
168: */
169: void rejectValue(String field, String errorCode,
170: Object[] errorArgs, String defaultMessage);
171:
172: /**
173: * Add all errors from the given <code>Errors</code> instance to this
174: * <code>Errors</code> instance.
175: * <p>This is a onvenience method to avoid repeated <code>reject(..)</code>
176: * calls for merging an <code>Errors</code> instance into another
177: * <code>Errors</code> instance.
178: * <p>Note that the passed-in <code>Errors</code> 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</code> instance.
181: * @param errors the <code>Errors</code> 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 List of {@link ObjectError} instances
198: */
199: List getAllErrors();
200:
201: /**
202: * Are there any global errors?
203: * @return <code>true</code> 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 List of ObjectError instances
218: */
219: List getGlobalErrors();
220:
221: /**
222: * Get the <i>first</i> global error, if any.
223: * @return the global error, or <code>null</code>
224: */
225: ObjectError getGlobalError();
226:
227: /**
228: * Are there any field errors?
229: * @return <code>true</code> if there are any errors associated with a field
230: * @see #hasGlobalErrors()
231: */
232: boolean hasFieldErrors();
233:
234: /**
235: * Return the number of errors associated with a field.
236: * @return the number of errors associated with a field
237: * @see #getGlobalErrorCount()
238: */
239: int getFieldErrorCount();
240:
241: /**
242: * Get all errors associated with a field.
243: * @return a List of {@link FieldError} instances
244: */
245: List getFieldErrors();
246:
247: /**
248: * Get the <i>first</i> error associated with a field, if any.
249: * @return the field-specific error, or <code>null</code>
250: */
251: FieldError getFieldError();
252:
253: /**
254: * Are there any errors associated with the given field?
255: * @param field the field name
256: * @return <code>true</code> if there were any errors associated with the given field
257: */
258: boolean hasFieldErrors(String field);
259:
260: /**
261: * Return the number of errors associated with the given field.
262: * @param field the field name
263: * @return the number of errors associated with the given field
264: */
265: int getFieldErrorCount(String field);
266:
267: /**
268: * Get all errors associated with the given field.
269: * <p>Implementations should support not only full field names like
270: * "name" but also pattern matches like "na*" or "address.*".
271: * @param field the field name
272: * @return a List of {@link FieldError} instances
273: */
274: List getFieldErrors(String field);
275:
276: /**
277: * Get the first error associated with the given field, if any.
278: * @param field the field name
279: * @return the field-specific error, or <code>null</code>
280: */
281: FieldError getFieldError(String field);
282:
283: /**
284: * Return the current value of the given field, either the current
285: * bean property value or a rejected update from the last binding.
286: * <p>Allows for convenient access to user-specified field values,
287: * even if there were type mismatches.
288: * @param field the field name
289: * @return the current value of the given field
290: */
291: Object getFieldValue(String field);
292:
293: /**
294: * Return the type of a given field.
295: * <p>Implementations should be able to determine the type even
296: * when the field value is <code>null</code>, for example from some
297: * associated descriptor.
298: * @param field the field name
299: * @return the type of the field, or <code>null</code> if not determinable
300: */
301: Class getFieldType(String field);
302:
303: }
|