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 006 package fc.web.simpleforms; 007 008 import javax.servlet.*; 009 import javax.servlet.http.*; 010 import java.io.*; 011 import java.util.*; 012 013 import fc.io.*; 014 015 /** 016 Convenience class to store arbitrary form validation errors 017 and messages. This class should be instantiated per request 018 as needed (when there are form validation errors). 019 <p> 020 Note: This class is not thread-safe but that's not a concern 021 since only each seperate user request is handled by at 022 most 1 thread. 023 024 @author hursh jain 025 **/ 026 public final class Errors 027 { 028 Log log = Log.getDefault(); 029 030 List formErrors; 031 Map fieldErrors; 032 List formWarnings; 033 Map fieldWarnings; 034 035 /** 036 Adds a form level error, typically associated with the form 037 itself and/or multiple fields as a group. 038 */ 039 public void addFormError(String msg) 040 { 041 if (formErrors == null) 042 formErrors = new ArrayList(); 043 044 formErrors.add(msg); 045 } 046 047 /** 048 Adds 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 */ 056 public 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 /** 068 Adds an arbitrary warning message generated as part of form processing 069 */ 070 public void addFormWarning(String msg) 071 { 072 if (formWarnings == null) 073 formWarnings = new ArrayList(); 074 075 formWarnings.add(msg); 076 } 077 078 /** 079 Adds an arbitrary warning message generated as part of form 080 processing. This warning is associated with the specified field. 081 */ 082 public 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 /** 094 Returns a list of all form errors or null if no errors are present. 095 */ 096 public List getFormErrors() { 097 return formErrors; 098 } 099 100 /** 101 Returns the field error for the specified fieldname or null if no 102 error was found. 103 */ 104 public Object getFieldError(String fieldName) 105 { 106 if (fieldErrors == null) 107 return null; 108 109 return fieldErrors.get(fieldName); 110 } 111 112 /** 113 Returns the list of all form-level warnings or <tt>null</tt> if no 114 warnings exist for the form. 115 */ 116 public List getFormWarnings() { 117 return formWarnings; 118 } 119 120 /** 121 Returns the warning for the specified field or <tt>null</tt> if 122 no warning exists. 123 */ 124 public Object getFieldWarning(String fieldname) { 125 return fieldWarnings.get(fieldname); 126 } 127 128 /** 129 Returns true if there are any form or field errors. (although 130 warnings are allowed) 131 */ 132 public boolean hasError() { 133 return formErrors != null || fieldErrors != null; 134 } 135 136 /** 137 Returns true if there are any warnings. 138 */ 139 public boolean hasWarning() { 140 return formWarnings != null || fieldWarnings != null; 141 } 142 143 /** 144 Returns true if there are any warnings for the specified <u>field</u> 145 */ 146 public boolean hasWarning(String fieldname) { 147 return fieldWarnings != null && fieldWarnings.containsKey(fieldname); 148 } 149 150 151 /** 152 Convenience method to render all the form errors (if present). 153 For more control, obtain the form errors and print them manually. 154 Invoking this method has the following effect: 155 <blockquote><pre> 156 String after = "<br>"; 157 List list = error.getFormErrors(); 158 if (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 */ 172 public 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 /** 196 Convenience method to render a field error. Invoking this 197 method is a shorthand for saying (where <tt>error</tt> is 198 an instance of this class): 199 <blockquote><pre> 200 Object obj = error.getFieldError("some_field_name"); 201 if (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> 208 The above is the same as: 209 <blockquote><pre> 210 error.<font color=blue>render</font>(out, "some_field_name"); 211 </pre></blockquote> 212 Note: The object representing the error for the field is written as 213 is. Typically for strings, this works fine. However, for more complex 214 objects (like say a list holding more than 1 error for the same field), 215 the list is printed as-is. For more formatting options for complex 216 objects, obtain and print the error manually. 217 */ 218 public 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 /** 236 Convenience method to render a field error. Invoking this 237 method is a shorthand for saying (where <tt>error</tt> is 238 an instance of this class): 239 <blockquote><pre> 240 Object obj = error.getFieldError("some_field_name"); 241 if (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> 249 The above is the same as (for example): 250 <blockquote><pre> 251 error.<font color=blue>render</font>(out, "some_field_name", <font color=blue>"inside"</font>, <font color=blue>"outside"</font>); 252 </pre></blockquote> 253 Note: The object representing the error for the field is written as 254 is. Typically for strings, this works fine. However, for more complex 255 objects (like say a list holding more than 1 error for the same field), 256 the list is printed as-is. For more formatting options for complex 257 objects, 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 */ 262 public 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 283 public 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 }