001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.wicket.validation;
018:
019: import java.util.ArrayList;
020: import java.util.Collections;
021: import java.util.HashMap;
022: import java.util.Iterator;
023: import java.util.List;
024: import java.util.Map;
025: import java.util.Map.Entry;
026:
027: import org.apache.wicket.IClusterable;
028:
029: /**
030: * A versatile implementation of {@link IValidationError} that supports message
031: * resolution from {@link IErrorMessageSource}, default message (if none of the
032: * keys matched), and variable substitution.
033: *
034: * The final error message is constructed via the following process:
035: * <ol>
036: * <li>Try all keys added by calls to {@link #addMessageKey(String)} via
037: * provided {@link IErrorMessageSource}</li>
038: * <li>If none of the keys yielded a message, use the message set by
039: * {@link #setMessage(String)} if any</li>
040: * <li>Perform variable subsitution on the message if any</li>
041: * </ol>
042: *
043: * @author ivaynberg
044: */
045: public class ValidationError implements IValidationError, IClusterable {
046: private static final long serialVersionUID = 1L;
047:
048: // XXX 2.0: optimization - keys can be null by default until a key is added
049: /** List of message keys to try against the {@link IErrorMessageSource} */
050: private final List keys = new ArrayList(1);
051:
052: /** Variable map to use in variable substitution */
053: private Map vars;
054:
055: /** Default message used when all keys yield no message */
056: private String message;
057:
058: /**
059: * Constructor
060: */
061: public ValidationError() {
062:
063: }
064:
065: /**
066: * Adds a key to the list of keys that will be tried against
067: * {@link IErrorMessageSource} to locate the error message string
068: *
069: * @param key
070: * @return this for chaining
071: */
072: public ValidationError addMessageKey(String key) {
073: if (key == null || key.trim().length() == 0) {
074: throw new IllegalArgumentException(
075: "Argument [[key]] cannot be null or an empty string");
076: }
077: keys.add(key);
078: return this ;
079: }
080:
081: /**
082: * Sets a variable that will be used in substitution
083: *
084: * @param name
085: * variable name
086: * @param value
087: * variable value
088: * @return this for chaining
089: */
090: public ValidationError setVariable(String name, Object value) {
091: if (name == null || name.trim().length() == 0) {
092: throw new IllegalArgumentException(
093: "Argument [[name]] cannot be null or an empty string");
094: }
095: if (value == null) {
096: throw new IllegalArgumentException(
097: "Argument [[value]] cannot be null or an empty string");
098: }
099:
100: getVariables().put(name, value);
101:
102: return this ;
103: }
104:
105: /**
106: * Returns the map of variables for this error. User is free to modify the
107: * contents.
108: *
109: * @return map of variables for this error
110: */
111: public final Map getVariables() {
112: if (vars == null) {
113: vars = new HashMap(2);
114: }
115: return vars;
116: }
117:
118: /**
119: * Sets the variable map for this error
120: *
121: * @param vars
122: * variable map
123: * @return this for chaining
124: */
125: public final ValidationError setVariables(Map vars) {
126: if (vars == null) {
127: throw new IllegalArgumentException(
128: "Argument [[vars]] cannot be null");
129: }
130: this .vars = vars;
131: return this ;
132: }
133:
134: /**
135: * @see org.apache.wicket.validation.IValidationError#getErrorMessage(org.apache.wicket.validation.IErrorMessageSource)
136: */
137: public final String getErrorMessage(
138: IErrorMessageSource messageSource) {
139: String errorMessage = null;
140:
141: // try any message keys ...
142: for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
143: errorMessage = messageSource.getMessage((String) iterator
144: .next());
145: if (errorMessage != null) {
146: break;
147: }
148: }
149:
150: // ... if no keys matched try the default
151: if (errorMessage == null && this .message != null) {
152: errorMessage = this .message;
153: }
154:
155: // if a message was found perform variable substitution
156: if (errorMessage != null) {
157: final Map p = (vars == null) ? Collections.EMPTY_MAP : vars;
158: errorMessage = messageSource.substitute(errorMessage, p);
159: }
160: return errorMessage;
161: }
162:
163: /**
164: * Gets message that will be used when no message could be located via
165: * message keys
166: *
167: * @return message
168: */
169: public final String getMessage() {
170: return message;
171: }
172:
173: /**
174: * Sets message that will be used when no message could be located via
175: * message keys
176: *
177: * @param message
178: * the message
179: *
180: * @return this for chaining
181: */
182: public final ValidationError setMessage(String message) {
183: if (message == null) {
184: throw new IllegalArgumentException(
185: "Argument [[defaultMessage]] cannot be null");
186: }
187: this .message = message;
188: return this ;
189: }
190:
191: /**
192: * @see java.lang.Object#toString()
193: */
194: public String toString() {
195: StringBuffer tostring = new StringBuffer();
196: tostring.append("[").append(getClass().getName());
197:
198: tostring.append(" message=[").append(message);
199:
200: tostring.append("], keys=[");
201: if (keys != null) {
202: Iterator i = keys.iterator();
203: while (i.hasNext()) {
204: tostring.append(i.next());
205: if (i.hasNext()) {
206: tostring.append(", ");
207: }
208: }
209: } else {
210: tostring.append("null");
211: }
212: tostring.append("], variables=[");
213:
214: if (vars != null) {
215: Iterator i = vars.entrySet().iterator();
216: while (i.hasNext()) {
217: final Map.Entry e = (Entry) i.next();
218: tostring.append("[").append(e.getKey()).append("=")
219: .append(e.getValue()).append("]");
220: if (i.hasNext()) {
221: tostring.append(",");
222: }
223: }
224: } else {
225: tostring.append("null");
226: }
227: tostring.append("]");
228:
229: tostring.append("]");
230:
231: return tostring.toString();
232: }
233:
234: }
|