001: /*
002: * Copyright (c) 2001 - 2005 ivata limited.
003: * All rights reserved.
004: * -----------------------------------------------------------------------------
005: * ivata masks may be redistributed under the GNU General Public
006: * License as published by the Free Software Foundation;
007: * version 2 of the License.
008: *
009: * These programs are free software; you can redistribute them and/or
010: * modify them under the terms of the GNU General Public License
011: * as published by the Free Software Foundation; version 2 of the License.
012: *
013: * These programs are distributed in the hope that they will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016: *
017: * See the GNU General Public License in the file LICENSE.txt for more
018: * details.
019: *
020: * If you would like a copy of the GNU General Public License write to
021: *
022: * Free Software Foundation, Inc.
023: * 59 Temple Place - Suite 330
024: * Boston, MA 02111-1307, USA.
025: *
026: *
027: * To arrange commercial support and licensing, contact ivata at
028: * http://www.ivata.com/contact.jsp
029: * -----------------------------------------------------------------------------
030: * $Log: ValidationErrorsConvertor.java,v $
031: * Revision 1.10 2005/10/12 18:36:58 colinmacleod
032: * Standardized format of Logger declaration - to make it easier to find instances
033: * which are not both static and final.
034: *
035: * Revision 1.9 2005/10/11 18:54:06 colinmacleod
036: * Fixed some checkstyle and javadoc issues.
037: *
038: * Revision 1.8 2005/10/03 10:17:25 colinmacleod
039: * Fixed some style and javadoc issues.
040: *
041: * Revision 1.7 2005/10/02 14:06:34 colinmacleod
042: * Added/improved log4j logging.
043: *
044: * Revision 1.6 2005/04/09 18:04:19 colinmacleod
045: * Changed copyright text to GPL v2 explicitly.
046: *
047: * Revision 1.5 2005/03/10 10:44:35 colinmacleod
048: * Fixed validation conversion of Struts classes to
049: * ivata masks validation errors.
050: *
051: * Revision 1.4 2005/01/19 13:14:02 colinmacleod
052: * Renamed CausedByException to SystemException.
053: *
054: * Revision 1.3 2005/01/07 08:08:25 colinmacleod
055: * Moved up a version number.
056: * Changed copyright notices to 2005.
057: * Updated the documentation:
058: * - started working on multiproject:site docu.
059: * - changed the logo.
060: * Added checkstyle and fixed LOADS of style issues.
061: * Added separate thirdparty subproject.
062: * Added struts (in web), util and webgui (in webtheme) from ivata op.
063: *
064: * Revision 1.2 2004/12/23 21:28:32 colinmacleod
065: * Modifications to add ivata op compatibility.
066: *
067: * Revision 1.1.1.1 2004/05/16 20:40:33 colinmacleod
068: * Ready for 0.1 release
069: *
070: * Revision 1.3 2004/03/21 21:16:23 colinmacleod
071: * Shortened name to ivata op.
072: *
073: * Revision 1.2 2004/02/01 22:07:29 colinmacleod
074: * Added full names to author tags
075: *
076: * Revision 1.1 2004/01/29 13:48:41 janboros
077: * Moved ivata op to SourceForge
078: *
079: * Revision 1.5 2003/02/26 17:10:38 peter
080: * toActionError: the bundle is located by java.util, not struts
081: *
082: * Revision 1.4 2003/02/24 19:08:17 colin
083: * *** empty log message ***
084: *
085: * Revision 1.3 2003/02/20 20:24:11 colin
086: * improved validation by adding ValidationField and ValidationException
087: *
088: * Revision 1.2 2003/02/04 17:36:47 colin
089: * copyright notice
090: *
091: * Revision 1.1 2002/11/12 10:41:12 colin
092: * first version in CVS. encapsulates Struts class ActionErrors
093: * -----------------------------------------------------------------------------
094: */
095: package com.ivata.mask.web.struts;
096:
097: import java.util.Iterator;
098: import java.util.List;
099: import java.util.Locale;
100: import java.util.Vector;
101:
102: import org.apache.log4j.Logger;
103: import org.apache.struts.action.ActionErrors;
104: import org.apache.struts.action.ActionMessage;
105:
106: import com.ivata.mask.field.Field;
107: import com.ivata.mask.util.SystemException;
108: import com.ivata.mask.validation.ValidationError;
109: import com.ivata.mask.validation.ValidationErrors;
110: import com.ivata.mask.web.struts.util.MaskMessageResources;
111:
112: /**
113: * <p>
114: * Converts ivata masks validation errors to struts action errors. This class
115: * has been split off from <code>ValidationErrors</code>, which was
116: * originally a part of <a href="http://www.ivata.org">ivata op </a> and <a
117: * href="http://www.ivata.com/portal">ivata team portal </a>.
118: * </p>.
119: *
120: * @since ivata masks 0.4 (2002-11-11)
121: * @author Colin MacLeod
122: * <a href='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com</a>
123: * @version $Revision: 1.10 $
124: * @see ValidationError
125: * @see org.apache.struts.action.ActionErrors
126: */
127: public final class ValidationErrorsConvertor {
128: /**
129: * Logger for this class.
130: */
131: private static final Logger logger = Logger
132: .getLogger(ValidationErrorsConvertor.class);
133: /**
134: * Default text to use when there is no field.
135: */
136: private static final String NONE_FIELD = "[None]";
137:
138: /**
139: * Private helper to avoid repetition. Get the label for the field specified
140: * and default it if the label is not available.
141: *
142: * @param locale <copyDoc>Refer to {@link #toActionErrors}.</copyDoc>
143: * @param bundle name of the resource bundle used to translate the field
144: * label.
145: * @param resourceFieldPath path within the bundle which prefixes the field
146: * name.
147: * @param field field whose label should be retrieved.
148: * @return localized text for this label.
149: * @throws SystemException Refer to
150: * @link MessageResourcesHandling#getDefaultLabel}.
151: */
152: private static String getFieldLabel(final Locale locale,
153: final String bundle, final String resourceFieldPath,
154: final Field field) throws SystemException {
155: if (logger.isDebugEnabled()) {
156: logger.debug("getFieldLabel(Locale locale = " + locale
157: + ", String bundle = " + bundle
158: + ", String resourceFieldPath = "
159: + resourceFieldPath + ", Field field = " + field
160: + ") - start");
161: }
162:
163: String fieldLabel;
164: try {
165: MaskMessageResources messageResources = new MaskMessageResources(
166: locale, bundle, resourceFieldPath);
167: fieldLabel = messageResources.getDefaultLabel(field
168: .getName(), null, null, null, false, false);
169: } catch (Exception e) {
170: // just log this exception - we don't want to report errors about
171: // our error-handing - it could go on forever ;-)
172: logger.error(e);
173: fieldLabel = null;
174: }
175: // if we can't find a label, just put out what we know
176: // about this field - it will be better than [null]
177: if (fieldLabel == null) {
178: fieldLabel = bundle + "-" + resourceFieldPath + "-"
179: + field.getName();
180: logger.error("No label found for " + "field '" + fieldLabel
181: + "'");
182: }
183:
184: if (logger.isDebugEnabled()) {
185: logger.debug("getFieldLabel - end - return value = "
186: + fieldLabel);
187: }
188: return fieldLabel;
189: }
190:
191: /**
192: * <p>
193: * Convert the errors to instances of <code>ActionError</code> for use in
194: * a <strong>Struts </strong> project.
195: * </p>
196: *
197: * @param locale Current system locale we should use in error message
198: * texts.
199: * @param validationErrors contains error references which should be
200: * converted to plain text errors.
201: * @return {@link org.apache.struts.action.ActionErrors ActionErrors}
202: * collection containing <code>ActionError</code> instances whose
203: * contents mirror that of the <code>ValidationError</code>
204: * instances this instance contains.
205: * @throws SystemException if the message resources are undefined.
206: */
207: public static ActionErrors toActionErrors(
208: final ValidationErrors validationErrors, final Locale locale)
209: throws SystemException {
210: if (logger.isDebugEnabled()) {
211: logger
212: .debug("toActionErrors(ValidationErrors validationErrors = "
213: + validationErrors
214: + ", Locale locale = "
215: + locale + ") - start");
216: }
217:
218: assert (validationErrors != null);
219:
220: List errors = validationErrors.getErrors();
221: ActionErrors actionErrors = new ActionErrors();
222: for (Iterator i = errors.iterator(); i.hasNext();) {
223: ValidationError error = (ValidationError) i.next();
224: Field field = error.getField();
225: String key = error.getErrorKey();
226: List originalParameters = error.getParameters();
227: // convert any parameters from ValidationField to basic type
228: Vector parameters = new Vector();
229: // the first parameter is always the field itself
230: String fieldName;
231: if (field == null) {
232: fieldName = NONE_FIELD;
233: parameters.add(NONE_FIELD);
234: } else {
235: fieldName = field.getName();
236: parameters.add(getFieldLabel(locale, error.getBundle(),
237: error.getResourceFieldPath(), field));
238: }
239:
240: if (originalParameters != null) {
241: for (Iterator j = originalParameters.iterator(); j
242: .hasNext();) {
243: Object parameter = j.next();
244: if (parameter instanceof Field) {
245: String label = getFieldLabel(locale, error
246: .getBundle(), error
247: .getResourceFieldPath(),
248: (Field) parameter);
249: parameters.add(label);
250: } else {
251: parameters.add(parameter);
252: }
253: }
254: }
255: // 0 parameters
256: int count;
257: count = parameters.size();
258: int parameterCount = 0;
259: if ((parameters == null) || (count == parameterCount++)) {
260: actionErrors.add(fieldName, new ActionMessage(key));
261: // 1 parameter
262: } else if (count == parameterCount++) {
263: actionErrors.add(fieldName, new ActionMessage(key,
264: parameters.get(0)));
265: // 2 parameters
266: } else if (count == parameterCount++) {
267: parameterCount = 0;
268: actionErrors.add(fieldName, new ActionMessage(key,
269: parameters.get(parameterCount++), parameters
270: .get(parameterCount++)));
271: // 3 parameters
272: } else if (count == parameterCount++) {
273: parameterCount = 0;
274: actionErrors.add(fieldName, new ActionMessage(key,
275: parameters.get(parameterCount++), parameters
276: .get(parameterCount++), parameters
277: .get(parameterCount++)));
278: // 4 parameters or more
279: } else if (count >= parameterCount) {
280: // can't go beyond this limit yet TODO: horrid, magic number
281: // workaround stuff here :-)
282: if (count > parameterCount) {
283: logger
284: .warn(parameterCount
285: + " parameters "
286: + " encountered for key '"
287: + key
288: + "'. All parameters are: "
289: + parameters
290: + ". ActionMessage constructor only lets us have "
291: + "the first 4 - the rest will be ignored.");
292: }
293: parameterCount = 0;
294: actionErrors.add(fieldName, new ActionMessage(key,
295: parameters.get(parameterCount++), parameters
296: .get(parameterCount++), parameters
297: .get(parameterCount++), parameters
298: .get(parameterCount++)));
299: // more are not allowed :-(
300: }
301: }
302:
303: if (logger.isDebugEnabled()) {
304: logger.debug("toActionErrors - end - return value = "
305: + actionErrors);
306: }
307: return actionErrors;
308: }
309:
310: /**
311: * Private constructor enforces utility class behavior.
312: */
313: private ValidationErrorsConvertor() {
314: }
315: }
|