1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.dbforms.validation;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.commons.validator.Arg;
29 import org.apache.commons.validator.Field;
30 import org.apache.commons.validator.Form;
31 import org.apache.commons.validator.ValidatorAction;
32 import org.apache.commons.validator.ValidatorResources;
33 import org.apache.commons.validator.ValidatorUtil;
34 import org.apache.commons.validator.Var;
35
36 import org.dbforms.config.Constants;
37 import org.dbforms.config.DbFormsErrors;
38
39 import org.dbforms.util.MessageResources;
40 import org.dbforms.util.Util;
41
42 import java.util.ArrayList;
43 import java.util.Collections;
44 import java.util.Comparator;
45 import java.util.Enumeration;
46 import java.util.Hashtable;
47 import java.util.Iterator;
48 import java.util.List;
49 import java.util.Locale;
50 import java.util.Map;
51
52
53
54 /***********************************************************************************************
55 * This class generate error string from ResourceBundle if enable,
56 * else generate error in DbForms-Error.xml standard.
57 *
58 * @author Eric Beaumier
59 **********************************************************************************************/
60 public class DbFormsValidatorUtil {
61 static Log logCat = LogFactory.getLog(DbFormsValidatorUtil.class.getName());
62
63 /***********************************************************************************************
64 * Retrieve <arg> parameter from validation.xml.
65 *
66 * @param <code>String</code> : Type of validation (required, range, email,...).
67 * @param <code>Locale</code> : Locale object to map with the good ResourceBundle
68 * @param <code>Field</code> : Field validator information. (retrieve <arg_> tag from validation.xml).
69 *
70 *
71 * @return <code>String</code> : Message resolve.
72 **********************************************************************************************/
73 public static String[] getArgs(String actionName,
74 Locale locale,
75 Field field) {
76 Arg arg0 = field.getArg0(actionName);
77 Arg arg1 = field.getArg1(actionName);
78 Arg arg2 = field.getArg2(actionName);
79 Arg arg3 = field.getArg3(actionName);
80
81 String sArg0 = null;
82 String sArg1 = null;
83 String sArg2 = null;
84 String sArg3 = null;
85
86 if (arg0 != null) {
87 if (arg0.getResource()) {
88 sArg0 = MessageResources.getMessage(arg0.getKey(), locale);
89
90 if (sArg0 == null) {
91 sArg0 = arg0.getKey();
92 }
93 } else {
94 sArg0 = arg0.getKey();
95 }
96 } else {
97 sArg0 = field.getKey();
98 }
99
100 if (arg1 != null) {
101 if (arg1.getResource()) {
102 sArg1 = MessageResources.getMessage(arg1.getKey(), locale);
103
104 if (sArg1 == null) {
105 sArg1 = arg1.getKey();
106 }
107 } else {
108 sArg1 = arg1.getKey();
109 }
110 }
111
112 if (arg2 != null) {
113 if (arg2.getResource()) {
114 sArg2 = MessageResources.getMessage(arg2.getKey(), locale);
115
116 if (sArg2 == null) {
117 sArg2 = arg2.getKey();
118 }
119 } else {
120 sArg2 = arg2.getKey();
121 }
122 }
123
124 if (arg3 != null) {
125 if (arg3.getResource()) {
126 sArg3 = MessageResources.getMessage(arg3.getKey(), locale);
127
128 if (sArg3 == null) {
129 sArg3 = arg3.getKey();
130 }
131 } else {
132 sArg3 = arg3.getKey();
133 }
134 }
135
136 return new String[] {
137 sArg0,
138 sArg1,
139 sArg2,
140 sArg3
141 };
142 }
143
144
145 /***********************************************************************************************
146 * J A V S C R I P T G E N E R A T I O N.
147 *
148 * @param <code>formName</code> : Name to match with <form> in validation.xml.
149 * @param <code>Locale</code> : Locale object to map with the ResourceBundle
150 * @param <code>Hashtable</code> : Hashtable of field name in table and generated name from DbForms (ex: "field1" : "f_4_3@root_4").
151 * @param <code>ValidatorResources</code> : ValidatorResources use by DbForms
152 * @param <code>javascriptValidationSrcFile</code> : Validation file name to include in src of script. <SCRIPT src="..."></SCRIPT>
153 * @param <code>DbFormsErrors</code> : Class to resolve DbForms-Error format (DbForms-Errors.xml).
154 *
155 * @return <code>StringBuffer</code> : The complete javascript validation section to include in response.
156 **********************************************************************************************/
157 public static StringBuffer getJavascript(List formNames,
158 Locale locale,
159 Hashtable fieldsName,
160 ValidatorResources resources,
161 String javascriptValidationSrcFile,
162 DbFormsErrors errors) {
163 StringBuffer results = new StringBuffer();
164 StringBuffer jsFunctions = new StringBuffer();
165 boolean bJavascriptSrcFile = (javascriptValidationSrcFile != null);
166
167 Form form = null;
168 String formName = "";
169
170
171 List lActions = new ArrayList();
172 List lActionMethods = new ArrayList();
173
174 for (Iterator formIterator = formNames.iterator();
175 formIterator.hasNext();) {
176 formName = (String) formIterator.next();
177
178 if ((form = resources.get(locale, formName)) != null) {
179
180 for (Iterator i = form.getFields()
181 .iterator(); i.hasNext();) {
182 Field field = (Field) i.next();
183
184
185
186 if (!fieldsName.containsValue(field.getProperty())) {
187 continue;
188 }
189
190 for (Iterator x = field.getDependencies()
191 .iterator(); x.hasNext();) {
192 Object o = x.next();
193
194 if ((o != null) && !lActionMethods.contains(o)) {
195 lActionMethods.add(o);
196 }
197 }
198 }
199 }
200 }
201
202
203 for (Iterator i = lActionMethods.iterator(); i.hasNext();) {
204 String actionName = (String) i.next();
205 ValidatorAction va = resources.getValidatorAction(actionName);
206
207 if (va != null) {
208 String javascript = va.getJavascript();
209
210 if ((javascript != null) && (javascript.length() > 0)) {
211 lActions.add(va);
212 } else {
213 i.remove();
214 }
215 } else {
216 i.remove();
217 }
218 }
219
220 Collections.sort(lActions,
221 new Comparator() {
222 public int compare(Object o1,
223 Object o2) {
224 ValidatorAction va1 = (ValidatorAction) o1;
225 ValidatorAction va2 = (ValidatorAction) o2;
226
227 if (((va1.getDepends() == null)
228 || (va1.getDepends()
229 .length() == 0))
230 && ((va2.getDepends() == null)
231 || (va2.getDepends()
232 .length() == 0))) {
233 return 0;
234 } else if (((va1.getDepends() != null)
235 && (va1.getDepends()
236 .length() > 0))
237 && ((va2.getDepends() == null)
238 || (va2.getDepends()
239 .length() == 0))) {
240 return 1;
241 } else if (((va1.getDepends() == null)
242 || (va1.getDepends()
243 .length() == 0))
244 && ((va2.getDepends() != null)
245 && (va2.getDepends()
246 .length() > 0))) {
247 return -1;
248 } else {
249 return va1.getDependencies()
250 .size() - va2.getDependencies()
251 .size();
252 }
253 }
254 });
255
256 String methods = null;
257
258 for (Iterator i = lActions.iterator(); i.hasNext();) {
259 ValidatorAction va = (ValidatorAction) i.next();
260
261 if (methods == null) {
262 methods = va.getMethod() + "(form)";
263 } else {
264 methods += (" && " + va.getMethod() + "(form)");
265 }
266 }
267
268 results.append(getJavascriptBegin(formName, methods));
269
270 for (Iterator i = lActions.iterator(); i.hasNext();) {
271 ValidatorAction va = (ValidatorAction) i.next();
272 String jscriptVar = null;
273 String functionName = null;
274
275 if ((va.getJsFunctionName() != null)
276 && (va.getJsFunctionName()
277 .length() > 0)) {
278 functionName = va.getJsFunctionName();
279 } else {
280 functionName = va.getName();
281 }
282
283 if (!bJavascriptSrcFile) {
284 jsFunctions.append(va.getJavascript());
285 jsFunctions.append("\n\n");
286 }
287
288 results.append(" function " + functionName + " () { \n");
289
290 for (Iterator formIterator = formNames.iterator();
291 formIterator.hasNext();) {
292 formName = (String) formIterator.next();
293
294 if ((form = resources.get(locale, formName)) != null) {
295 for (Iterator x = form.getFields()
296 .iterator(); x.hasNext();) {
297 Field field = (Field) x.next();
298
299
300
301 if (!field.isIndexed() && field.isDependency(va.getName())) {
302 String message = getMessage(functionName, va, locale,
303 field, errors);
304 Enumeration e = fieldsName.keys();
305
306 while (e.hasMoreElements()) {
307 String fieldName = (String) e.nextElement();
308 String val = (String) fieldsName.get(fieldName);
309
310 if (field.getKey()
311 .equals(val)) {
312 jscriptVar = getNextVar(jscriptVar);
313
314
315
316
317
318
319 if (fieldName.indexOf(Constants.FIELDNAME_INSERTPREFIX) != -1) {
320
321 results.append("\t if(")
322 .append(ValidatorConstants.JS_UPDATE_VALIDATION_MODE)
323 .append("==false) ");
324 } else {
325
326 results.append("\t if(")
327 .append(ValidatorConstants.JS_UPDATE_VALIDATION_MODE)
328 .append("==true) ");
329 }
330
331 results.append(" this.dbforms_" + jscriptVar
332 + " = new Array(\"" + fieldName
333 + "\", \"" + message + "\", ");
334 results.append("new Function (\"varName\", \"");
335
336 Map hVars = field.getVars();
337
338
339 for (Iterator iVars = hVars.keySet()
340 .iterator();
341 iVars.hasNext();) {
342 String varKey = (String) iVars.next();
343 Var var = (Var) hVars.get(varKey);
344 String varValue = var.getValue();
345 String jsType = var.getJsType();
346
347 if (Var.JSTYPE_INT.equalsIgnoreCase(jsType)) {
348 results.append("this." + varKey + "="
349 + ValidatorUtil.replace(varValue,
350 "//",
351 "////")
352 + "; ");
353 } else if (Var.JSTYPE_REGEXP.equalsIgnoreCase(jsType)) {
354 results.append("this." + varKey + "=/"
355 + ValidatorUtil.replace(varValue,
356 "//",
357 "////")
358 + "/; ");
359 } else if (Var.JSTYPE_STRING.equalsIgnoreCase(jsType)) {
360 results.append("this." + varKey + "='"
361 + ValidatorUtil.replace(varValue,
362 "//",
363 "////")
364 + "'; ");
365 }
366
367 else if ("mask".equalsIgnoreCase(varKey)) {
368 results.append("this." + varKey + "=/"
369 + ValidatorUtil.replace(varValue,
370 "//",
371 "////")
372 + "/; ");
373 } else {
374 results.append("this." + varKey + "='"
375 + ValidatorUtil.replace(varValue,
376 "//",
377 "////")
378 + "'; ");
379 }
380 }
381
382 results.append(" return this[varName];\"));\n");
383 }
384 }
385 }
386 }
387 }
388 }
389
390 results.append(" } \n\n");
391 }
392
393
394 if (!bJavascriptSrcFile) {
395 results.append(jsFunctions.toString());
396 }
397
398 results.append(getJavascriptEnd());
399
400 if (bJavascriptSrcFile) {
401 results.append("\n<SCRIPT language=\"javascript\" src=\""
402 + javascriptValidationSrcFile + "\"></SCRIPT> \n");
403 }
404
405 return results;
406 }
407
408
409 /***********************************************************************************************
410 * Get the error message from ResourceBundle if present, else generate a DbForms-Error.xml standard.
411 *
412 * @param <code>String</code> : Type of validation (required, range, email,...).
413 * @param <code>ValidatorAction</code> : ValidatorAction to retrieve validation definition.
414 * @param <code>Locale</code> : Locale object to map with the good ResourceBundle
415 * @param <code>Field</code> : Field validator information. (retrieve <arg_> tag from validation.xml).
416 * @param <code>DbFormsErrors</code> : DbForms Error class to retrieve error message in DbForm-Errors.xml format.
417 *
418 * @return <code>String</code> : Message resolve.
419 **********************************************************************************************/
420 public static String getMessage(String type,
421 ValidatorAction va,
422 Locale locale,
423 Field field,
424 DbFormsErrors errors) {
425 String result = null;
426 String[] arg = getArgs(va.getName(), locale, field);
427 String msg = ((field.getMsg(va.getName()) != null)
428 ? field.getMsg(va.getName())
429 : va.getMsg());
430
431 if (msg == null) {
432 msg = "errors." + va.getName();
433 }
434
435 //***************************************************
436 // Try to resolve message with Application Resource
437 //**************************************************
438 result = MessageResources.getMessage(msg, locale, arg);
439
440 if (result != null) {
441 return result;
442 }
443
444 //**************************************************
445 // ELSE Generate DbForms-Error.xml standard
446 //**************************************************
447 result = msg + ":";
448
449 for (int i = 0; i < arg.length; i++) {
450 if (arg[i] != null) {
451 result += (arg[i] + ",");
452 }
453 }
454
455 // 2003-01-30 HKK: Removed trailing ,
456 result = result.substring(0, result.length() - 1);
457
458 // 2002-09-12 HKK: Catch errors while getXMLErrorMessage!
459 try {
460 result = errors.getXMLErrorMessage(result);
461 } catch (Exception e) {
462 logCat.error("Not in proper format - do not try to convert!");
463 }
464
465 return result;
466 }
467
468
469 //*********************************************************************************************
470 // ***
471 // *** P R I V A T E U S E
472 // ***
473 //*********************************************************************************************
474 private static String getJavascriptBegin(String formName,
475 String methods) {
476 StringBuffer sb = new StringBuffer();
477 String name = Character.toUpperCase(formName.charAt(0))
478 + formName.substring(1, formName.length());
479
480 sb.append("<script language=\"Javascript1.1\"> \n");
481
482 sb.append("<!-- Begin \n");
483 sb.append("\n var " + ValidatorConstants.JS_CANCEL_VALIDATION
484 + " = false;");
485 sb.append("\n var " + ValidatorConstants.JS_UPDATE_VALIDATION_MODE
486 + " = true; \n\n");
487
488 sb.append(" function validate" + name + "(form) { \n");
489
490 sb.append(" if (!" + ValidatorConstants.JS_CANCEL_VALIDATION
491 + ") \n");
492 sb.append(" return true; \n");
493 sb.append(" else \n");
494
495 // Always return true if there aren't any Javascript validation methods
496 if (Util.isNull(methods)) {
497 sb.append(" return true; \n");
498 } else {
499 sb.append(" return " + methods + "; \n");
500 }
501
502 sb.append(" } \n\n");
503
504 return sb.toString();
505 }
506
507
508 private static String getJavascriptEnd() {
509 StringBuffer sb = new StringBuffer();
510
511 sb.append("\n");
512 sb.append("// End -->\n");
513 sb.append("</script>\n\n");
514
515 return sb.toString();
516 }
517
518
519 private static String getNextVar(String input) {
520 if (input == null) {
521 return "aa";
522 }
523
524 input = input.toLowerCase();
525
526 for (int i = input.length(); i > 0; i--) {
527 int pos = i - 1;
528
529 char c = input.charAt(pos);
530 c++;
531
532 if (c <= 'z') {
533 if (i == 0) {
534 return c + input.substring(pos, input.length());
535 } else if (i == input.length()) {
536 return input.substring(0, pos) + c;
537 } else {
538 return input.substring(0, pos) + c
539 + input.substring(pos, input.length() - 1);
540 }
541 } else {
542 input = replaceChar(input, pos, 'a');
543 }
544 }
545
546 return null;
547 }
548
549
550 private static String replaceChar(String input,
551 int pos,
552 char c) {
553 if (pos == 0) {
554 return c + input.substring(pos, input.length());
555 } else if (pos == input.length()) {
556 return input.substring(0, pos) + c;
557 } else {
558 return input.substring(0, pos) + c
559 + input.substring(pos, input.length() - 1);
560 }
561 }
562 }