KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > validation > DefaultMessageCodesResolver


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.validation;
18
19 import java.io.Serializable JavaDoc;
20 import java.util.ArrayList JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.List JavaDoc;
23
24 import org.springframework.util.StringUtils;
25
26 /**
27  * Default implementation of the {@link MessageCodesResolver} interface.
28  *
29  * <p>Will create two message codes for an object error, in the following order:
30  * <ul>
31  * <li>1.: code + "." + object name
32  * <li>2.: code
33  * </ul>
34  *
35  * <p>Will create four message codes for a field specification, in the following order:
36  * <ul>
37  * <li>1.: code + "." + object name + "." + field
38  * <li>2.: code + "." + field
39  * <li>3.: code + "." + field type
40  * <li>4.: code
41  * </ul>
42  *
43  * <p>For example, in case of code "typeMismatch", object name "user", field "age":
44  * <ul>
45  * <li>1. try "typeMismatch.user.age"
46  * <li>2. try "typeMismatch.age"
47  * <li>3. try "typeMismatch.int"
48  * <li>4. try "typeMismatch"
49  * </ul>
50  *
51  * <p>This resolution algorithm thus can be leveraged for example to show
52  * specific messages for binding errors like "required" and "typeMismatch":
53  * <ul>
54  * <li>at the object + field level ("age" field, but only on "user");
55  * <li>at the field level (all "age" fields, no matter which object name);
56  * <li>or at the general level (all fields, on any object).
57  * </ul>
58  *
59  * <p>In case of array, {@link List} or {@link java.util.Map} properties,
60  * both codes for specific elements and for the whole collection are
61  * generated. Assuming a field "name" of an array "groups" in object "user":
62  * <ul>
63  * <li>1. try "typeMismatch.user.groups[0].name"
64  * <li>2. try "typeMismatch.user.groups.name"
65  * <li>3. try "typeMismatch.groups[0].name"
66  * <li>4. try "typeMismatch.groups.name"
67  * <li>5. try "typeMismatch.name"
68  * <li>6. try "typeMismatch.java.lang.String"
69  * <li>7. try "typeMismatch"
70  * </ul>
71  *
72  * <p>In order to group all codes into a specific category within your resource bundles,
73  * e.g. "validation.typeMismatch.name" instead of the default "typeMismatch.name",
74  * consider specifying a {@link #setPrefix prefix} to be applied.
75  *
76  * @author Juergen Hoeller
77  * @since 1.0.1
78  */

79 public class DefaultMessageCodesResolver implements MessageCodesResolver, Serializable JavaDoc {
80
81     /**
82      * The separator that this implementation uses when resolving message codes.
83      */

84     public static final String JavaDoc CODE_SEPARATOR = ".";
85
86
87     private String JavaDoc prefix = "";
88
89
90     /**
91      * Specify a prefix to be applied to any code built by this resolver.
92      * <p>Default is none. Specify, for example, "validation." to get
93      * error codes like "validation.typeMismatch.name".
94      */

95     public void setPrefix(String JavaDoc prefix) {
96         this.prefix = (prefix != null ? prefix : "");
97     }
98
99     /**
100      * Return the prefix to be applied to any code built by this resolver.
101      * <p>Returns an empty String in case of no prefix.
102      */

103     protected String JavaDoc getPrefix() {
104         return this.prefix;
105     }
106
107
108     public String JavaDoc[] resolveMessageCodes(String JavaDoc errorCode, String JavaDoc objectName) {
109         return new String JavaDoc[] {
110                 postProcessMessageCode(errorCode + CODE_SEPARATOR + objectName),
111                 postProcessMessageCode(errorCode)};
112     }
113
114     /**
115      * Build the code list for the given code and field: an
116      * object/field-specific code, a field-specific code, a plain error code.
117      * <p>Arrays, Lists and Maps are resolved both for specific elements and
118      * the whole collection.
119      * <p>See the {@link DefaultMessageCodesResolver class level Javadoc} for
120      * details on the generated codes.
121      * @return the list of codes
122      */

123     public String JavaDoc[] resolveMessageCodes(String JavaDoc errorCode, String JavaDoc objectName, String JavaDoc field, Class JavaDoc fieldType) {
124         List JavaDoc codeList = new ArrayList JavaDoc();
125         List JavaDoc fieldList = new ArrayList JavaDoc();
126         buildFieldList(field, fieldList);
127         for (Iterator JavaDoc it = fieldList.iterator(); it.hasNext();) {
128             String JavaDoc fieldInList = (String JavaDoc) it.next();
129             codeList.add(postProcessMessageCode(errorCode + CODE_SEPARATOR + objectName + CODE_SEPARATOR + fieldInList));
130         }
131         int dotIndex = field.lastIndexOf('.');
132         if (dotIndex != -1) {
133             buildFieldList(field.substring(dotIndex + 1), fieldList);
134         }
135         for (Iterator JavaDoc it = fieldList.iterator(); it.hasNext();) {
136             String JavaDoc fieldInList = (String JavaDoc) it.next();
137             codeList.add(postProcessMessageCode(errorCode + CODE_SEPARATOR + fieldInList));
138         }
139         if (fieldType != null) {
140             codeList.add(postProcessMessageCode(errorCode + CODE_SEPARATOR + fieldType.getName()));
141         }
142         codeList.add(postProcessMessageCode(errorCode));
143         return StringUtils.toStringArray(codeList);
144     }
145
146     /**
147      * Add both keyed and non-keyed entries for the supplied <code>field</code>
148      * to the supplied field list.
149      */

150     protected void buildFieldList(String JavaDoc field, List JavaDoc fieldList) {
151         fieldList.add(field);
152         String JavaDoc plainField = field;
153         int keyIndex = plainField.lastIndexOf('[');
154         while (keyIndex != -1) {
155             int endKeyIndex = plainField.indexOf(']', keyIndex);
156             if (endKeyIndex != -1) {
157                 plainField = plainField.substring(0, keyIndex) + plainField.substring(endKeyIndex + 1);
158                 fieldList.add(plainField);
159                 keyIndex = plainField.lastIndexOf('[');
160             }
161             else {
162                 keyIndex = -1;
163             }
164         }
165     }
166
167     /**
168      * Post-process the given message code, built by this resolver.
169      * <p>The default implementation applies the specified prefix, if any.
170      * @param code the message code as built by this resolver
171      * @return the final message code to be returned
172      * @see #setPrefix
173      */

174     protected String JavaDoc postProcessMessageCode(String JavaDoc code) {
175         return getPrefix() + code;
176     }
177
178 }
179
Popular Tags