View Javadoc

1   /*
2    * Copyright (c) 2001 - 2005 ivata limited.
3    * All rights reserved.
4    * -----------------------------------------------------------------------------
5    * ivata masks may be redistributed under the GNU General Public
6    * License as published by the Free Software Foundation;
7    * version 2 of the License.
8    *
9    * These programs are free software; you can redistribute them and/or
10   * modify them under the terms of the GNU General Public License
11   * as published by the Free Software Foundation; version 2 of the License.
12   *
13   * These programs are distributed in the hope that they will be useful,
14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16   *
17   * See the GNU General Public License in the file LICENSE.txt for more
18   * details.
19   *
20   * If you would like a copy of the GNU General Public License write to
21   *
22   * Free Software Foundation, Inc.
23   * 59 Temple Place - Suite 330
24   * Boston, MA 02111-1307, USA.
25   *
26   *
27   * To arrange commercial support and licensing, contact ivata at
28   *                  http://www.ivata.com/contact.jsp
29   * -----------------------------------------------------------------------------
30   * $Log: ValidationErrorsConvertor.java,v $
31   * Revision 1.6  2005/04/09 18:04:19  colinmacleod
32   * Changed copyright text to GPL v2 explicitly.
33   *
34   * Revision 1.5  2005/03/10 10:44:35  colinmacleod
35   * Fixed validation conversion of Struts classes to
36   * ivata masks validation errors.
37   *
38   * Revision 1.4  2005/01/19 13:14:02  colinmacleod
39   * Renamed CausedByException to SystemException.
40   *
41   * Revision 1.3  2005/01/07 08:08:25  colinmacleod
42   * Moved up a version number.
43   * Changed copyright notices to 2005.
44   * Updated the documentation:
45   *   - started working on multiproject:site docu.
46   *   - changed the logo.
47   * Added checkstyle and fixed LOADS of style issues.
48   * Added separate thirdparty subproject.
49   * Added struts (in web), util and webgui (in webtheme) from ivata op.
50   *
51   * Revision 1.2  2004/12/23 21:28:32  colinmacleod
52   * Modifications to add ivata op compatibility.
53   *
54   * Revision 1.1.1.1  2004/05/16 20:40:33  colinmacleod
55   * Ready for 0.1 release
56   *
57   * Revision 1.3  2004/03/21 21:16:23  colinmacleod
58   * Shortened name to ivata op.
59   *
60   * Revision 1.2  2004/02/01 22:07:29  colinmacleod
61   * Added full names to author tags
62   *
63   * Revision 1.1  2004/01/29 13:48:41  janboros
64   * Moved ivata op to SourceForge
65   *
66   * Revision 1.5  2003/02/26 17:10:38  peter
67   * toActionError: the bundle is located by java.util, not struts
68   *
69   * Revision 1.4  2003/02/24 19:08:17  colin
70   * *** empty log message ***
71   *
72   * Revision 1.3  2003/02/20 20:24:11  colin
73   * improved validation by adding ValidationField and ValidationException
74   *
75   * Revision 1.2  2003/02/04 17:36:47  colin
76   * copyright notice
77   *
78   * Revision 1.1  2002/11/12 10:41:12  colin
79   * first version in CVS. encapsulates Struts class ActionErrors
80   * -----------------------------------------------------------------------------
81   */
82  package com.ivata.mask.web.struts;
83  import java.util.Iterator;
84  import java.util.List;
85  import java.util.Locale;
86  import java.util.Vector;
87  
88  import org.apache.log4j.Logger;
89  import org.apache.struts.action.ActionErrors;
90  import org.apache.struts.action.ActionMessage;
91  
92  import com.ivata.mask.field.Field;
93  import com.ivata.mask.util.SystemException;
94  import com.ivata.mask.validation.ValidationError;
95  import com.ivata.mask.validation.ValidationErrors;
96  import com.ivata.mask.web.struts.util.MessageResourcesHandling;
97  /***
98   * <p>
99   * Converts ivata masks validation errors to struts action errors. This class
100  * has been split off from <code>ValidationErrors</code>, which was
101  * originally a part of <a href="http://www.ivata.org">ivata op </a> and <a
102  * href="http://www.ivata.com/portal">ivata team portal </a>.
103  * </p>.
104  *
105  * @since ivata masks 0.4 (2002-11-11)
106  * @author Colin MacLeod
107  * <a href='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com</a>
108  * @version $Revision: 1.6 $
109  * @see ValidationError
110  * @see org.apache.struts.action.ActionErrors
111  */
112 public final class ValidationErrorsConvertor {
113     /***
114      * Refer to {@link Logger}.
115      */
116     private static Logger log =
117         Logger.getLogger(ValidationErrorsConvertor.class);
118     /***
119      * Default text to use when there is no field.
120      */
121     private static final String NONE_FIELD = "[None]";
122     /***
123      * Private helper to avoid repetition. Get the label for the field specified
124      * and default it if the label is not available.
125      *
126      * @param locale Refer to {@link #toActionErrors}.
127      * @param bundle name of the resource bundle used to translate the field
128      * label.
129      * @param resourceFieldPath path within the bundle which prefixes the field
130      * name.
131      * @param field field whose label should be retrieved.
132      * @return localized text for this label.
133      * @throws SystemException Refer to
134      * @link MessageResourcesHandling#getDefaultLabel}.
135      */
136     private static String getFieldLabel(Locale locale, String bundle,
137             String resourceFieldPath, Field field)
138             throws SystemException {
139         String fieldLabel;
140         try {
141             fieldLabel = MessageResourcesHandling.getDefaultLabel(
142                 locale, bundle, field.getName(),
143                 null, null, resourceFieldPath, null,
144                 false,
145                 false);
146         } catch (Exception e) {
147             // just log this exception - we don't want to report errors about
148             // our error-handing - it could go on forever ;-)
149             log.error(e);
150             fieldLabel = null;
151         }
152         // if we can't find a label, just put out what we know
153         // about this field - it will be better than [null]
154         if (fieldLabel == null) {
155             fieldLabel = bundle
156                     + "-"
157                     + resourceFieldPath
158                     + "-"
159                     + field.getName();
160             log.error("No label found for "
161                     + "field '"
162                     + fieldLabel
163                     + "'");
164         }
165         return fieldLabel;
166     }
167     /***
168      * <p>
169      * Convert the errors to instances of <code>ActionError</code> for use in
170      * a <strong>Struts </strong> project.
171      * </p>
172      *
173      * @param messages This instance is used to localize the error strings.
174      * @param validationErrors contains error references which should be
175      * converted to plain text errors.
176      * @return {@link org.apache.struts.action.ActionErrors ActionErrors}
177      *         collection containing <code>ActionError</code> instances whose
178      *         contents mirror that of the <code>ValidationError</code>
179      *         instances this instance contains.
180      * @throws SystemException if the message resources are undefined.
181      */
182     public static ActionErrors toActionErrors(
183             final ValidationErrors validationErrors,
184             final Locale locale)
185             throws SystemException {
186         assert (validationErrors != null);
187 
188         List errors = validationErrors.getErrors();
189         ActionErrors actionErrors = new ActionErrors();
190         for (Iterator i = errors.iterator(); i.hasNext();) {
191             ValidationError error = (ValidationError) i.next();
192             Field field = error.getField();
193             String key = error.getErrorKey();
194             List originalParameters = error.getParameters();
195             // convert any parameters from ValidationField to basic type
196             Vector parameters = new Vector();
197             // the first parameter is always the field itself
198             String fieldName;
199             if (field == null) {
200                 fieldName= NONE_FIELD;
201                 parameters.add(NONE_FIELD);
202             } else {
203                 fieldName = field.getName();
204                 parameters.add(getFieldLabel(locale, error.getBundle(),
205                         error.getResourceFieldPath(), field));
206             }
207 
208             if (originalParameters != null) {
209                 for (Iterator j = originalParameters.iterator(); j.hasNext();) {
210                     Object parameter = j.next();
211                     if (parameter instanceof Field) {
212                         String label = getFieldLabel(locale, error.getBundle(),
213                                 error.getResourceFieldPath(),
214                                 (Field) parameter);
215                         parameters.add(label);
216                     } else {
217                         parameters.add(parameter);
218                     }
219                 }
220             }
221             // 0 parameters
222             int count;
223             count = parameters.size();
224             int parameterCount = 0;
225             if ((parameters == null) || (count == parameterCount++)) {
226                 actionErrors.add(fieldName, new ActionMessage(key));
227             // 1 parameter
228             } else if (count == parameterCount++) {
229                 actionErrors.add(fieldName,
230                         new ActionMessage(key, parameters.get(0)));
231             // 2 parameters
232             } else if (count == parameterCount++) {
233                 parameterCount = 0;
234                 actionErrors.add(fieldName,
235                         new ActionMessage(key,
236                                 parameters.get(parameterCount++),
237                                 parameters.get(parameterCount++)));
238             // 3 parameters
239             } else if (count == parameterCount++) {
240                 parameterCount = 0;
241                 actionErrors.add(fieldName,
242                         new ActionMessage(key,
243                                 parameters.get(parameterCount++),
244                                 parameters.get(parameterCount++),
245                                 parameters.get(parameterCount++)));
246             // 4 parameters or more
247             } else if (count >= parameterCount){
248                 // can't go beyond this limit yet TODO: horrid, magic number
249                 // workaround stuff here :-)
250                 if (count > parameterCount) {
251                     log.warn(parameterCount
252                             + " parameters "
253                             + " encountered for key '"
254                             + key
255                             + "'. All parameters are: "
256                             + parameters
257                             + ". ActionMessage constructor only lets us have "
258                             + "the first 4 - the rest will be ignored.");
259                 }
260                 parameterCount = 0;
261                 actionErrors.add(fieldName,
262                         new ActionMessage(key,
263                                 parameters.get(parameterCount++),
264                                 parameters.get(parameterCount++),
265                                 parameters.get(parameterCount++),
266                                 parameters.get(parameterCount++)));
267             // more are not allowed :-(
268             }
269         }
270         return actionErrors;
271     }
272 
273     /***
274      * Private constructor enforces utility class behavior.
275      */
276     private ValidationErrorsConvertor () {
277     }
278 }
279