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.taglib;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28
29 import org.dbforms.config.Constants;
30 import org.dbforms.config.Field;
31 import org.dbforms.config.FieldTypes;
32 import org.dbforms.config.ResultSetVector;
33
34 import org.dbforms.event.AbstractWebEvent;
35 import org.dbforms.event.eventtype.EventType;
36 import org.dbforms.interfaces.IEscaper;
37
38 import org.dbforms.util.MessageResources;
39 import org.dbforms.util.MessageResourcesInternal;
40 import org.dbforms.util.ParseUtil;
41 import org.dbforms.util.ReflectionUtil;
42 import org.dbforms.util.Util;
43
44 import java.text.Format;
45
46 import java.util.Locale;
47 import java.util.Vector;
48
49 import javax.servlet.http.HttpServletRequest;
50 import javax.servlet.jsp.JspException;
51
52 /***
53 * <p>
54 * Base class for db-tags that render form data-elements capable of including
55 * JavaScript event handlers and/or CSS Style attributes.
56 * </p>
57 *
58 * <p>
59 * Furthermore, this base class provides base functionality for DataBase driven
60 * form widgets: it initializes the associated DbFormsConfig and provides
61 * various field-properties & methods (i.e getFormFieldName and
62 * getFormFieldValue)
63 * </p>
64 *
65 * <p>
66 * the html/css releated properties and methods where originally done by Don
67 * Clasen for Apache Groups's Jakarta-Struts project.
68 * </p>
69 *
70 * <p>
71 * Added support for Custom Formatter class, see SetCustomFormatter.java Author
72 * Neal Katz .
73 * </p>
74 *
75 * <p>
76 * Added support for overrideFormFieldName attribute. useful when working with
77 * customcontrollers. Author Neal Katz .
78 * </p>
79 * orginally done by Don Clasen
80 *
81 * @author Joe Peer (modified and extended this class for use in
82 * DbForms-Project)
83 */
84 public abstract class AbstractDbBaseHandlerTag extends AbstractScriptHandlerTag {
85 private static Log logCat = LogFactory.getLog(AbstractDbBaseHandlerTag.class
86 .getName());
87
88 private DbFormTag parentForm;
89
90 private IEscaper escaper = null;
91
92 private Field field;
93
94
95 private String customFormatter = null;
96
97 private String defaultValue;
98
99 private String escaperClass = null;
100
101 private String fieldName;
102
103 private String maxlength = null;
104
105 private String nullFieldValue;
106
107
108 private String pattern;
109
110 private String readOnly = "false";
111
112 /*** Named Style class associated with component for read-only mode. */
113 private String readOnlyStyleClass = null;
114
115 /***
116 * DOCUMENT ME!
117 *
118 * @param string
119 */
120 public void setCustomFormatter(String string) {
121 customFormatter = string;
122 }
123
124 /***
125 * DOCUMENT ME!
126 *
127 * @param value
128 * DOCUMENT ME!
129 */
130 public void setDefaultValue(String value) {
131 this.defaultValue = value;
132 }
133
134 /***
135 * "value" is only used if parent tag is in "insert-mode" (footer, etc.)
136 * otherwise this tag takes the current value from the database result!
137 *
138 * @return DOCUMENT ME!
139 */
140 public String getDefaultValue() {
141 return defaultValue;
142 }
143
144 /***
145 * DOCUMENT ME!
146 *
147 * @return DOCUMENT ME!
148 */
149 public IEscaper getEscaper() {
150 if (escaper == null) {
151 String s = getEscaperClass();
152
153 if (!Util.isNull(s)) {
154 try {
155 escaper = (IEscaper) ReflectionUtil.newInstance(s);
156 } catch (Exception e) {
157 logCat
158 .error("cannot create the new escaper [" + s + "]",
159 e);
160 }
161 }
162
163 if ((escaper == null) && (getField() != null)) {
164 escaper = getField().getEscaper();
165 }
166
167 if ((escaper == null)) {
168 escaper = getConfig().getEscaper();
169 }
170 }
171
172 return escaper;
173 }
174
175 /***
176 * DOCUMENT ME!
177 *
178 * @param string
179 */
180 public void setEscaperClass(String string) {
181 escaperClass = string;
182 }
183
184 /***
185 * DOCUMENT ME!
186 *
187 * @return
188 */
189 public String getEscaperClass() {
190 return escaperClass;
191 }
192
193 /***
194 * DOCUMENT ME!
195 *
196 * @return
197 */
198 public Field getField() {
199 return field;
200 }
201
202 /***
203 * DOCUMENT ME!
204 *
205 * @param fieldName
206 * DOCUMENT ME!
207 */
208 public void setFieldName(String fieldName) {
209 this.fieldName = fieldName;
210
211 if (getParentForm().getTable() != null) {
212 setField(getParentForm().getTable().getFieldByName(fieldName));
213 } else {
214 setField(null);
215 }
216
217 if (getParentForm().isSubForm() && (this.field != null)) {
218
219
220 getParentForm().strikeOut(this.field);
221 }
222 }
223
224 /***
225 * formatting a value
226 *
227 * @return DOCUMENT ME!
228 */
229 protected Format getFormatter() {
230 Format res = null;
231 if (getField() != null) {
232 res = getField().getFormat(pattern, getLocale());
233 }
234 return res;
235 }
236
237 /***
238 * Sets the maxlength
239 *
240 * @param maxlength
241 * The maxlength to set
242 */
243 public void setMaxlength(String maxlength) {
244 this.maxlength = maxlength;
245 }
246
247 /***
248 * Gets the maxlength
249 *
250 * @return Returns a String
251 */
252 public String getMaxlength() {
253 return maxlength;
254 }
255
256 /***
257 * DOCUMENT ME!
258 *
259 * @return
260 */
261 public String getName() {
262 return (getField() != null) ? getField().getName() : fieldName;
263 }
264
265 /***
266 * Sets the nullFieldValue attribute of the DbLabelTag object
267 *
268 * @param nullFieldValue
269 * The new nullFieldValue value
270 */
271 public void setNullFieldValue(String nullFieldValue) {
272 this.nullFieldValue = nullFieldValue;
273 }
274
275 /***
276 * DOCUMENT ME!
277 *
278 * @param parent
279 * DOCUMENT ME!
280 */
281 public void setParent(final javax.servlet.jsp.tagext.Tag parent) {
282 super.setParent(parent);
283
284
285
286 parentForm = (DbFormTag) findAncestorWithClass(this, DbFormTag.class);
287 }
288
289 /***
290 * DOCUMENT ME!
291 *
292 * @param string
293 */
294 public void setPattern(String string) {
295 pattern = string;
296 }
297
298 /***
299 * DOCUMENT ME!
300 *
301 * @return
302 */
303 public String getPattern() {
304 Format f = getFormatter();
305
306 if (f == null) {
307 return null;
308 }
309
310 return Util.getPattern(f);
311 }
312
313 /***
314 * Sets the read-only attribute.
315 *
316 * @param readOnly
317 * DOCUMENT ME!
318 */
319 public void setReadOnly(String readOnly) {
320 this.readOnly = readOnly;
321 }
322
323 /***
324 * Sets the style class attribute for read-only mode.
325 *
326 * @param readOnlyStyleClass
327 * DOCUMENT ME!
328 */
329 public void setReadOnlyStyleClass(String readOnlyStyleClass) {
330 this.readOnlyStyleClass = readOnlyStyleClass;
331 }
332
333 /***
334 * Returns the style class attribute for read-only mode.
335 *
336 * @return DOCUMENT ME!
337 */
338 public String getReadOnlyStyleClass() {
339 return readOnlyStyleClass;
340 }
341
342 /***
343 * DOCUMENT ME!
344 *
345 * @return DOCUMENT ME!
346 */
347 public String getStyleClass() {
348 boolean readonly = hasReadOnlySet() || getParentForm().hasReadOnlySet();
349
350 if (readonly && !Util.isNull(getReadOnlyStyleClass())) {
351 return getReadOnlyStyleClass();
352 } else {
353 return super.getStyleClass();
354 }
355 }
356
357 /***
358 * DOCUMENT ME!
359 *
360 * @param s
361 *
362 * @return
363 */
364 protected String customFormat(String s) {
365 return SetCustomFormatterTag.sprintf(customFormatter, pageContext, s);
366 }
367
368 /***
369 * DOCUMENT ME!
370 */
371 public void doFinally() {
372 field = null;
373 defaultValue = null;
374 pattern = null;
375 nullFieldValue = null;
376 maxlength = null;
377 readOnlyStyleClass = null;
378 readOnly = "false";
379 escaperClass = null;
380 escaper = null;
381 customFormatter = null;
382 super.doFinally();
383 }
384
385 /***
386 * Returns the read-only attribute.
387 *
388 * @return DOCUMENT ME!
389 */
390 public boolean hasReadOnlySet() {
391 return Util.getTrue(readOnly);
392 }
393
394 /***
395 * DOCUMENT ME!
396 *
397 * @return
398 */
399 protected String getCustomFormatter() {
400 return customFormatter;
401 }
402
403 /***
404 * DOCUMENT ME!
405 *
406 * @param field
407 * DOCUMENT ME!
408 */
409 protected void setField(Field field) {
410 this.field = field;
411 }
412
413 /***
414 * return the object value from the database
415 *
416 * @return the object
417 */
418 protected Object getFieldObject() {
419 Object fieldValueObj = null;
420 ResultSetVector res = getParentForm().getResultSetVector();
421
422 if ((res != null) && (getField() != null)) {
423 fieldValueObj = res.getFieldAsObject(getField().getName());
424 } else {
425
426 fieldValueObj = ParseUtil.getParameter(
427 (HttpServletRequest) pageContext.getRequest(),
428 getFormFieldName());
429
430 if (fieldValueObj == null) {
431
432
433 fieldValueObj = getDefaultValue();
434 } else {
435 fieldValueObj = (getEscaper() == null) ? fieldValueObj
436 : getEscaper().unescapeHTML((String) fieldValueObj);
437 }
438 }
439
440 return fieldValueObj;
441 }
442
443 /***
444 * fetches the value from the database. if no value is given, contents of
445 * attribute nullFieldValue is returned.
446 *
447 * @return the field value
448 */
449 protected String getFieldValue() {
450 ResultSetVector rsv = getParentForm().getResultSetVector();
451 String res = null;
452
453 if ((getField() != null) && (rsv != null)) {
454 String[] s = rsv.getCurrentRow();
455
456 if (s != null) {
457 res = rsv.getCurrentRow()[getField().getId()];
458 }
459 }
460
461 return res;
462 }
463
464 /***
465 * DOCUMENT ME!
466 *
467 * @return DOCUMENT ME!
468 */
469 protected String getFormFieldDefaultValue() {
470 if (defaultValue != null) {
471
472
473 return defaultValue;
474 }
475
476
477
478 return typicalDefaultValue();
479 }
480
481 /***
482 * generates the decoded name for the html-widget.
483 *
484 * @return DOCUMENT ME!
485 */
486 protected String getFormFieldName() {
487
488 StringBuffer buf = new StringBuffer();
489
490 if ((getParentForm().getTable() != null) && (getField() != null)) {
491 String keyIndex = (getParentForm().isFooterReached()) ? (Constants.FIELDNAME_INSERTPREFIX + getParentForm()
492 .getPositionPathCore())
493 : getParentForm().getPositionPath();
494 buf.append(Constants.FIELDNAME_PREFIX);
495 buf.append(getParentForm().getTable().getId());
496 buf.append("_");
497 buf.append(keyIndex);
498 buf.append("_");
499 buf.append(getField().getId());
500 } else {
501 buf.append(fieldName);
502 }
503
504 return buf.toString();
505 }
506
507 /***
508 * Philip Grunikiewicz 2001-05-31 determinates value of the html-widget. In
509 * a jsp which contains many input fields, it may be desirable, in the event
510 * of an error, to redisplay input data. (instead of refreshing the fields
511 * from the DB) Currently dbforms implements this functionality with INSERT
512 * fields only. The following describes the changes I've implemented: - I've
513 * added a new attribute in the Form tag which sets the functionality
514 * (redisplayFieldsOnError=true/false) - I've modified the code below to
515 * handle the redisplay of previously posted information
516 *
517 * @return DOCUMENT ME!
518 */
519 protected String getFormFieldValue() {
520 HttpServletRequest request = (HttpServletRequest) this.pageContext
521 .getRequest();
522 Vector errors = (Vector) request.getAttribute("errors");
523 AbstractWebEvent we = getParentForm().getWebEvent();
524
525
526 if (!getParentForm().isFooterReached()) {
527
528
529 if ((getParentForm().hasRedisplayFieldsOnErrorSet()
530 && (errors != null) && (errors.size() > 0))
531 || ((we != null) && EventType.EVENT_NAVIGATION_RELOAD
532 .equals(we.getType()))) {
533
534 String oldValue = ParseUtil.getParameter(request,
535 getFormFieldName());
536
537 if (oldValue != null) {
538 return oldValue;
539 }
540 }
541
542 return getFormattedFieldValue();
543 } else {
544
545 if (((we != null) && (EventType.EVENT_NAVIGATION_COPY.equals(we
546 .getType())))) {
547 String copyValue = ParseUtil.getParameter(request,
548 getFormFieldNameForCopyEvent());
549
550 if (copyValue != null) {
551 return copyValue;
552 }
553 }
554
555 if (((we != null) && EventType.EVENT_NAVIGATION_RELOAD.equals(we
556 .getType()))
557 || ((errors != null) && (errors.size() > 0))) {
558 String oldValue = ParseUtil.getParameter(request,
559 getFormFieldName());
560
561 if (oldValue != null) {
562 return oldValue;
563 }
564
565
566
567
568
569 if (this instanceof DbCheckboxTag) {
570 return typicalDefaultValue() + "_";
571 }
572 }
573 if (getField() == null) {
574 String oldValue = ParseUtil.getParameter(request,
575 getFormFieldName());
576
577 if (oldValue != null) {
578 return oldValue;
579 }
580 }
581
582 return getFormFieldDefaultValue();
583 }
584 }
585
586 /***
587 * fetches the value from the database. if no value is given, contents of
588 * attribute nullFieldValue is returned.
589 *
590 * @return the field value
591 */
592 protected String getFormattedFieldValue() {
593 Object fieldValueObj = getFieldObject();
594 String res;
595
596 if (fieldValueObj == null) {
597 res = getNullFieldValue();
598 } else {
599
600
601
602
603
604
605
606 if (fieldValueObj.getClass().isArray()
607 && "byte".equals(fieldValueObj.getClass()
608 .getComponentType().toString())) {
609 res = new String((byte[]) fieldValueObj);
610 } else if (getField() != null) {
611 switch (getField().getType()) {
612 case FieldTypes.INTEGER:
613 case FieldTypes.DOUBLE:
614 case FieldTypes.FLOAT:
615 case FieldTypes.NUMERIC:
616 case FieldTypes.DATE:
617 case FieldTypes.TIME:
618 case FieldTypes.TIMESTAMP:
619
620 try {
621 res = getFormatter().format(fieldValueObj);
622 } catch (Exception e) {
623 logCat.error("field type: " + getField().getType()
624 + "\n" + "object type: "
625 + fieldValueObj.getClass().getName() + "\n"
626 + "pattern: " + getPattern() + "\n"
627 + e.getMessage());
628 res = fieldValueObj.toString();
629 }
630
631 break;
632
633 case FieldTypes.BLOB:
634 case FieldTypes.DISKBLOB:
635 case FieldTypes.CHAR:
636 case FieldTypes.VARCHAR:
637 case FieldTypes.LONGVARCHAR:
638 default:
639 res = fieldValueObj.toString();
640
641 break;
642 }
643 } else {
644 res = fieldValueObj.toString();
645 }
646 }
647
648 res = customFormat(res);
649 return res;
650 }
651
652 /***
653 * DOCUMENT ME!
654 *
655 * @return DOCUMENT ME!
656 */
657 protected Locale getLocale() {
658 return getParentForm().getLocale();
659 }
660
661
662 /***
663 * DOCUMENT ME!
664 *
665 * @return DOCUMENT ME!
666 */
667 protected DbFormTag getParentForm() {
668 return parentForm;
669 }
670
671 /***
672 * Just a shortcut for calling the escaper
673 *
674 * @param html
675 * string to escape
676 *
677 * @return escaped string
678 */
679 protected String escapeHTML(String html) {
680 return (getEscaper() == null) ? html : getEscaper().escapeHTML(html);
681 }
682
683 /***
684 * writes out the field value in hidden field _old
685 *
686 * @return DOCUMENT ME!
687 */
688 protected String renderOldValueHtmlInputField() {
689 StringBuffer tagBuf = new StringBuffer();
690 tagBuf.append("<input type=\"hidden\" name=\"");
691 tagBuf.append(Constants.FIELDNAME_OLDVALUETAG + getFormFieldName());
692 tagBuf.append("\" value=\"");
693
694 if (!getParentForm().isFooterReached()) {
695 tagBuf.append(escapeHTML(getFormattedFieldValue()));
696 } else {
697 tagBuf.append(escapeHTML(getFormFieldDefaultValue()));
698 }
699
700 tagBuf.append("\" />");
701
702 return tagBuf.toString();
703 }
704
705 /***
706 * writes out the current used format to the page
707 *
708 * @return DOCUMENT ME!
709 *
710 * @throws JspException
711 */
712 protected String renderPatternHtmlInputField() {
713 StringBuffer tagBuf = new StringBuffer();
714 String ppattern = getPattern();
715
716 if (!Util.isNull(ppattern)) {
717 tagBuf.append("<input type=\"hidden\" name=\"");
718 tagBuf.append(Constants.FIELDNAME_PATTERNTAG + getFormFieldName());
719 tagBuf.append("\" value=\"");
720 tagBuf.append(ppattern);
721 tagBuf.append("\" />");
722 }
723
724 return tagBuf.toString();
725 }
726
727 /***
728 * DOCUMENT ME!
729 *
730 * @return DOCUMENT ME!
731 */
732 protected String typicalDefaultValue() {
733
734 String res = "";
735
736 if (getField() != null) {
737 switch (field.getType()) {
738 case org.dbforms.config.FieldTypes.INTEGER:
739 case org.dbforms.config.FieldTypes.NUMERIC:
740 case org.dbforms.config.FieldTypes.DOUBLE:
741 case org.dbforms.config.FieldTypes.FLOAT:
742
743 try {
744 res = getFormatter().format(new Double(0));
745 } catch (Exception e) {
746 res = "0";
747 }
748
749
750 }
751 }
752
753 return res;
754 }
755
756 /***
757 * writes out all hidden fields for the input fields
758 */
759 protected void writeOutSpecialValues() throws JspException {
760 try {
761 pageContext.getOut().write(renderOldValueHtmlInputField());
762 } catch (java.io.IOException ioe) {
763 throw new JspException("IO Error: " + ioe.getMessage());
764 }
765 }
766
767 /***
768 * generates the decoded name for the html-widget in the case of copy
769 * events.
770 *
771 * @return DOCUMENT ME!
772 */
773 private String getFormFieldNameForCopyEvent() {
774 boolean footerReached = getParentForm().isFooterReached();
775 getParentForm().setFooterReached(false);
776
777 String name = getFormFieldName();
778 getParentForm().setFooterReached(footerReached);
779
780 return name;
781 }
782
783 /***
784 * Gets the nullFieldValue attribute of the DbLabelTag object
785 *
786 * @return The nullFieldValue value
787 */
788 private String getNullFieldValue() {
789 String res = nullFieldValue;
790
791 if (res == null) {
792 res = MessageResourcesInternal.getMessage("dbforms.nodata",
793 getLocale());
794 }
795
796
797 if ((getParentForm() != null)
798 && getParentForm().hasCaptionResourceSet()) {
799 res = MessageResources.getMessage(res, getLocale(), res);
800 }
801
802 /***
803 * Philip Grunikiewicz 2003-12-04 The data being return has a value of
804 * null. The developer has not specified a substitute. So instead of
805 * crashing, lets display an empty string!
806 */
807 if (res == null) {
808 res = "";
809 }
810
811 return res;
812 }
813
814
815 }