001// Copyright (c) 2001 Hursh Jain (http://www.mollypages.org) 002// The Molly framework is freely distributable under the terms of an 003// MIT-style license. For details, see the molly pages web site at: 004// http://www.mollypages.org/. Use, modify, have fun ! 005 006package fc.web.simpleforms; 007 008import javax.servlet.*; 009import javax.servlet.http.*; 010import java.io.*; 011import java.util.*; 012 013import fc.io.*; 014 015/** 016Convenience class to store arbitrary form validation errors 017and messages. This class should be instantiated per request 018as needed (when there are form validation errors). 019<p> 020Note: This class is not thread-safe but that's not a concern 021since only each seperate user request is handled by at 022most 1 thread. 023 024@author hursh jain 025**/ 026public final class Errors 027{ 028Log log = Log.getDefault(); 029 030List formErrors; 031Map fieldErrors; 032List formWarnings; 033Map fieldWarnings; 034 035/** 036Adds a form level error, typically associated with the form 037itself and/or multiple fields as a group. 038*/ 039public void addFormError(String msg) 040 { 041 if (formErrors == null) 042 formErrors = new ArrayList(); 043 044 formErrors.add(msg); 045 } 046 047/** 048Adds a field validation error 049 050@param fieldName the name of the field 051@param msg some error object, typically a string but 052 can be a list of strings (for example) if 053 there is more than 1 validation error for 054 this field 055*/ 056public void addFieldError(String fieldName, Object msg) 057 { 058 if (fieldErrors == null) 059 fieldErrors = new HashMap(); 060 061 Object old = fieldErrors.put(fieldName, msg); 062 if (old != null) { 063 log.warn("Use a list to add more than 1 message. I am currently over-writing the previous error message for field: " + fieldName + " [old msg=" + old + "] [new msg=" + msg + "]"); 064 } 065 } 066 067/** 068Adds an arbitrary warning message generated as part of form processing 069*/ 070public void addFormWarning(String msg) 071 { 072 if (formWarnings == null) 073 formWarnings = new ArrayList(); 074 075 formWarnings.add(msg); 076 } 077 078/** 079Adds an arbitrary warning message generated as part of form 080processing. This warning is associated with the specified field. 081*/ 082public void addFieldWarning(String fieldname, Object msg) 083 { 084 if (fieldWarnings == null) 085 fieldWarnings = new HashMap(); 086 087 Object old = fieldWarnings.put(fieldname, msg); 088 if (old != null) { 089 log.warn("Use a list to add more than 1 warning. I am currently over-writing the previous warning message for field: " + fieldname + " [old msg=" + old + "] [new msg=" + msg + "]"); 090 } 091 } 092 093/** 094Returns a list of all form errors or null if no errors are present. 095*/ 096public List getFormErrors() { 097 return formErrors; 098 } 099 100/** 101Returns the field error for the specified fieldname or null if no 102error was found. 103*/ 104public Object getFieldError(String fieldName) 105 { 106 if (fieldErrors == null) 107 return null; 108 109 return fieldErrors.get(fieldName); 110 } 111 112/** 113Returns the list of all form-level warnings or <tt>null</tt> if no 114warnings exist for the form. 115*/ 116public List getFormWarnings() { 117 return formWarnings; 118 } 119 120/** 121Returns the warning for the specified field or <tt>null</tt> if 122no warning exists. 123*/ 124public Object getFieldWarning(String fieldname) { 125 return fieldWarnings.get(fieldname); 126 } 127 128/** 129Returns true if there are any form or field errors. (although 130warnings are allowed) 131*/ 132public boolean hasError() { 133 return formErrors != null || fieldErrors != null; 134 } 135 136/** 137Returns true if there are any warnings. 138*/ 139public boolean hasWarning() { 140 return formWarnings != null || fieldWarnings != null; 141 } 142 143/** 144Returns true if there are any warnings for the specified <u>field</u> 145*/ 146public boolean hasWarning(String fieldname) { 147 return fieldWarnings != null && fieldWarnings.containsKey(fieldname); 148 } 149 150 151/** 152Convenience method to render all the form errors (if present). 153For more control, obtain the form errors and print them manually. 154Invoking this method has the following effect: 155<blockquote><pre> 156String after = "<br>"; 157List list = error.getFormErrors(); 158if (list != null) 159 { 160 out.write("<div class='form-errmsg'>"); 161 out.write("<ul>"); 162 for (int n = 0; n < list.size(); n++) { 163 out.write("<li>"); 164 out.write(String.valueOf(list.get(n))); 165 out.write("</li>"); 166 } 167 out.write("</ul>"); 168 out.write("</div>\n"); 169 } 170</pre></blockquote> 171*/ 172public void renderFormErrors(Writer out) throws IOException 173 { 174 if (formErrors == null) { 175 return; 176 } 177 178 if (formErrors == null) 179 return; 180 181 out.write("<div class='form-errmsg'>"); 182 out.write("\n<ul>"); 183 184 for (int n = 0; n < formErrors.size(); n++) { 185 Object obj = formErrors.get(n); 186 out.write("<li>"); 187 out.write(String.valueOf(obj)); 188 out.write("</li>\n"); 189 } 190 191 out.write("</ul>\n"); 192 out.write("</div>"); 193 } 194 195/** 196Convenience method to render a field error. Invoking this 197method is a shorthand for saying (where <tt>error</tt> is 198an instance of this class): 199<blockquote><pre> 200Object obj = error.getFieldError("some_field_name"); 201if (str != null) { 202 out.write("<span class='field-errmsg'>"); 203 out.write (String.valueOf(obj)); 204 out.write("</span>\n"); 205 out.write("<br>"); 206 } 207</pre></blockquote> 208The above is the same as: 209<blockquote><pre> 210error.<font color=blue>render</font>(out, "some_field_name"); 211</pre></blockquote> 212Note: The object representing the error for the field is written as 213is. Typically for strings, this works fine. However, for more complex 214objects (like say a list holding more than 1 error for the same field), 215the list is printed as-is. For more formatting options for complex 216objects, obtain and print the error manually. 217*/ 218public void render(Writer out, String fieldName) throws IOException 219 { 220 if (fieldErrors == null) { 221 return; 222 } 223 224 Object obj = fieldErrors.get(fieldName); 225 if (obj == null) 226 return; 227 228 out.write("<span class='field-errmsg'>"); 229 out.write(String.valueOf(obj)); 230 out.write("</span>"); 231 out.write("<br>"); 232 } 233 234 235/** 236Convenience method to render a field error. Invoking this 237method is a shorthand for saying (where <tt>error</tt> is 238an instance of this class): 239<blockquote><pre> 240Object obj = error.getFieldError("some_field_name"); 241if (str != null) { 242 out.write("<span class='field-errmsg'>"); 243 out.write (String.valueOf(obj)); 244 out.write(<font color=blue>"inside"</font>); 245 out.write("</span>\n"); 246 out.write(<font color=blue>"outside"</font>); 247 } 248</pre></blockquote> 249The above is the same as (for example): 250<blockquote><pre> 251error.<font color=blue>render</font>(out, "some_field_name", <font color=blue>"inside"</font>, <font color=blue>"outside"</font>); 252</pre></blockquote> 253Note: The object representing the error for the field is written as 254is. Typically for strings, this works fine. However, for more complex 255objects (like say a list holding more than 1 error for the same field), 256the list is printed as-is. For more formatting options for complex 257objects, obtain and print the error manually. 258 259@param inside this string is written before the span tag is closed 260@param outside this string is written right after the span tag is closed. 261*/ 262public void render( 263 Writer out, String fieldName, String inside, String outside) 264 throws IOException 265 { 266 if (fieldErrors == null) { 267 return; 268 } 269 270 Object obj = fieldErrors.get(fieldName); 271 if (obj == null) 272 return; 273 274 out.write("<span class='field-errmsg'>"); 275 out.write(String.valueOf(obj)); 276 out.write(inside); 277 out.write("</span>"); 278 out.write(outside); 279 } 280 281 282 283public static void main (String args[]) throws Exception 284 { 285 Errors e = new Errors(); 286 e.addFieldError("a", "some field error"); 287 List list = new ArrayList(); 288 list.add("item1"); 289 list.add("item2"); 290 e.addFieldError("b", list); 291 System.out.println("Has warnings: [should be false]: " + e.hasWarning()); 292 System.out.println("Has errors: [should be true]: " + e.hasError()); 293 e.addFormError("some form error"); 294 System.out.println("Has errors: [should be true]: " + e.hasError()); 295 PrintWriter pw = new PrintWriter(System.out); 296 pw.println("\n--------- form errors ---------"); 297 e.renderFormErrors(pw); 298 pw.println("\n--------- field errors [a]--------"); 299 e.render(pw, "a"); 300 pw.println("\n--------- field errors [b]--------"); 301 e.render(pw, "b"); 302 pw.println("\n--------- field errors [c/non-existent]--------"); 303 e.render(pw, "c"); 304 pw.flush(); 305 } 306 307}